<commit_before>use orbclient::{Renderer, Color};
use orbimage;
use std::cell::{ Cell, RefCell };
use std::sync::Arc;

use cell::CheckSet;
use event::Event;
use point::Point;
use rect::Rect;
use theme::{ ITEM_BACKGROUND, WINDOW_BACKGROUND, ITEM_SELECTION };
use traits::{ Click, Place };
use widgets::Widget;
use std::ops::Index;

/// An entry in a list
/// Each entry stores widgets within.
pub struct Entry {
    pub height: Cell<u32>,
    click_callback: RefCell<Option<Arc<Fn(&Entry, Point)>>>,
    widgets: RefCell<Vec<Arc<Widget>>>,
    pub highlight: Cell<Color>,
    highlighted: Cell<bool>,
}

impl Entry {
    pub fn new(h: u32) -> Arc<Self> {
        Arc::new(Entry {
            height: Cell::new(h),
            click_callback: RefCell::new(None),
            widgets: RefCell::new(vec![]),
            highlight: Cell::new(ITEM_SELECTION),
            highlighted: Cell::new(false),
        })
    }

    /// Adds a widget to the entry
    pub fn add<T: Widget>(&self, widget: &Arc<T>) {
        let mut widgets = self.widgets.borrow_mut();
        widgets.push(widget.clone());
    }

    fn widgets(&self) -> &RefCell<Vec<Arc<Widget>>> {
        &self.widgets
    }
}

impl Click for Entry {
    fn emit_click(&self, point: Point) {
        if let Some(ref click_callback) = *self.click_callback.borrow() {
            click_callback(self, point);
        }
    }

    fn on_click<T: Fn(&Self, Point) + 'static>(&self, func: T) -> &Self {
        *self.click_callback.borrow_mut() = Some(Arc::new(func));
        self
    }
}

pub struct List {
    pub rect: Cell<Rect>,
    v_scroll: Cell<i32>,
    current_height: Cell<u32>,
    entries: RefCell<Vec<Arc<Entry>>>,
    pressed: Cell<bool>,
    selected: Cell<Option<u32>>,
}

impl List {
    pub fn new() -> Arc<Self> {
        Arc::new(List {
            rect: Cell::new(Rect::default()),
            v_scroll: Cell::new(0),
            current_height: Cell::new(0),
            entries: RefCell::new(vec![]),
            pressed: Cell::new(false),
            selected: Cell::new(None),
        })
    }

    pub fn push(&self, entry: &Arc<Entry>) {
        let h = entry.height.get();
        self.entries.borrow_mut().push(entry.clone());
        self.current_height.set(self.current_height.get() + h);
    }

    // Given absolute coordinates, returns the list entry index
    // drawn at that point.
    fn get_entry_index(&self, p: Point) -> Option<u32> {
        if self.rect.get().contains(p) {
            let mut current_y = 0;
            let x = self.rect.get().x;
            let y = self.rect.get().y;
            let width = self.rect.get().width;
            let scroll = self.v_scroll.get();

            for (i, entry) in self.entries.borrow().iter().enumerate() {
                if Rect::new(x, y+current_y-scroll, width, entry.height.get()).contains(p) {
                    return Some(i as u32)
                }
                current_y += entry.height.get() as i32
            }
        }

        None
    }

    pub fn scroll(&self, y: i32) {
        let mut set_to = self.v_scroll.get() + y;
        if set_to < 0 {
            set_to = 0;
        } else if self.rect.get().height as i32 + set_to > self.current_height.get() as i32 {
            set_to = self.v_scroll.get() as i32;
        }
        self.v_scroll.set(set_to);
    }

    fn change_selection(&self, i: u32) {
        match self.selected.get() {
            Some(i) => {
                match self.entries.borrow().get(i as usize) {
                    Some(entry) => {
                        entry.highlighted.set(false);
                    },
                    None => {},
                }
            },
            _ => {},
        }

        if let Some(entry) = self.entries.borrow().get(i as usize) {
            entry.highlighted.set(true);
            self.selected.set(Some(i));

            let mut y = 0;

            for e in self.entries.borrow().index(0..(i as usize)) {
                y += e.height.get();
            }

            let v_scroll = self.v_scroll.get();

            if y < v_scroll as u32 {
                self.scroll(y as i32 - v_scroll);
            } else if (y + entry.height.get() as u32) > (v_scroll as u32 + self.rect.get().height) {
                self.scroll((y + entry.height.get()) as i32 - (v_scroll + self.rect.get().height as i32));
            }
        }
    }
}

impl Widget for List {
    fn rect(&self) -> &Cell<Rect> {
        &self.rect
    }

    fn draw(&self, renderer: &mut Renderer, _focused: bool) {
        let mut current_y = 0;
        let x = self.rect.get().x;
        let y = self.rect.get().y;
        let width = self.rect.get().width;
        let height = self.rect.get().height;

        let mut target = orbimage::Image::new(width, height);
        target.set(WINDOW_BACKGROUND);

        for entry in self.entries.borrow().iter() {
            let mut image = orbimage::Image::new(width, entry.height.get());

            if entry.highlighted.get() {
                image.set(entry.highlight.get());
            } else {
                image.set(ITEM_BACKGROUND);
            }

            for widget in entry.widgets().borrow().iter() {
                widget.draw(&mut image, false)
            }

            let image = image.data();
            target.image(x, current_y-self.v_scroll.get(), width, entry.height.get(), &image);

            current_y += entry.height.get() as i32
        }
        let target = target.data();
        renderer.image(x, y, width, height, &target)
    }

    fn event(&self, event: Event, focused: bool, redraw: &mut bool) -> bool {
        match event {
            Event::Mouse { point, left_button, .. } => {
                let mut click = false;

                let rect = self.rect.get();
                if rect.contains(point) {
                    if left_button {
                        if self.pressed.check_set(true) {
                            *redraw = true;
                        }
                    } else {
                        if self.pressed.check_set(false) {
                            click = true;
                            *redraw = true;
                        }
                    }
                } else {
                    if !left_button {
                        if self.pressed.check_set(false) {
                            *redraw = true;
                        }
                    }
                }

                if let Some(i) = self.get_entry_index(point) {
                    if click {
                        if let Some(entry) = self.entries.borrow().get(i as usize) {
                            entry.emit_click(point);
                        }
                    }

                    match self.selected.get() {
                        None => {
                            self.change_selection(i);
                            *redraw = true;
                        },
                        Some(selected) => {
                            if selected != i {
                                self.change_selection(i);
                                *redraw = true;
                            }
                        },
                    }
                }
            },
            Event::UpArrow => {
                match self.selected.get() {
                    None => {
                        self.change_selection(0);
                        *redraw = true;
                    },
                    Some(i) => {
                        if i > 0 {
                            self.change_selection(i - 1);
                            *redraw = true;
                        }
                    }
                }
            },
            Event::DownArrow => {
                match self.selected.get() {
                    None => {
                        self.change_selection(0);
                        *redraw = true;
                    },
                    Some(i) => {
                        if i < self.entries.borrow().len() as u32 - 1 {
                            self.change_selection(i + 1);
                            *redraw = true;
                        }
                    }
                }
            },
            Event::Home => {
                self.change_selection(0);
                *redraw = true
            },
            Event::End => {
                self.change_selection(self.entries.borrow().len() as u32 - 1);
                *redraw = true
            },
            Event::Enter => {
                match self.selected.get() {
                    Some(i) => {
                        match self.entries.borrow().get(i as usize) {
                            Some(entry) => {
                                entry.emit_click(Point { x: 0, y: 0});
                            },
                            None => {},
                        }
                    },
                    _ => {},
                }
            },
            Event::Scroll { y, .. } => {
                self.scroll(y * 2);
                *redraw = true;
            },
            _ => {}
        }
        focused
    }
}

impl Place for List {}

<commit_msg>Fix scroll direction in List widget<commit_after>use orbclient::{Renderer, Color};
use orbimage;
use std::cell::{ Cell, RefCell };
use std::sync::Arc;

use cell::CheckSet;
use event::Event;
use point::Point;
use rect::Rect;
use theme::{ ITEM_BACKGROUND, WINDOW_BACKGROUND, ITEM_SELECTION };
use traits::{ Click, Place };
use widgets::Widget;
use std::ops::Index;

/// An entry in a list
/// Each entry stores widgets within.
pub struct Entry {
    pub height: Cell<u32>,
    click_callback: RefCell<Option<Arc<Fn(&Entry, Point)>>>,
    widgets: RefCell<Vec<Arc<Widget>>>,
    pub highlight: Cell<Color>,
    highlighted: Cell<bool>,
}

impl Entry {
    pub fn new(h: u32) -> Arc<Self> {
        Arc::new(Entry {
            height: Cell::new(h),
            click_callback: RefCell::new(None),
            widgets: RefCell::new(vec![]),
            highlight: Cell::new(ITEM_SELECTION),
            highlighted: Cell::new(false),
        })
    }

    /// Adds a widget to the entry
    pub fn add<T: Widget>(&self, widget: &Arc<T>) {
        let mut widgets = self.widgets.borrow_mut();
        widgets.push(widget.clone());
    }

    fn widgets(&self) -> &RefCell<Vec<Arc<Widget>>> {
        &self.widgets
    }
}

impl Click for Entry {
    fn emit_click(&self, point: Point) {
        if let Some(ref click_callback) = *self.click_callback.borrow() {
            click_callback(self, point);
        }
    }

    fn on_click<T: Fn(&Self, Point) + 'static>(&self, func: T) -> &Self {
        *self.click_callback.borrow_mut() = Some(Arc::new(func));
        self
    }
}

pub struct List {
    pub rect: Cell<Rect>,
    v_scroll: Cell<i32>,
    current_height: Cell<u32>,
    entries: RefCell<Vec<Arc<Entry>>>,
    pressed: Cell<bool>,
    selected: Cell<Option<u32>>,
}

impl List {
    pub fn new() -> Arc<Self> {
        Arc::new(List {
            rect: Cell::new(Rect::default()),
            v_scroll: Cell::new(0),
            current_height: Cell::new(0),
            entries: RefCell::new(vec![]),
            pressed: Cell::new(false),
            selected: Cell::new(None),
        })
    }

    pub fn push(&self, entry: &Arc<Entry>) {
        let h = entry.height.get();
        self.entries.borrow_mut().push(entry.clone());
        self.current_height.set(self.current_height.get() + h);
    }

    // Given absolute coordinates, returns the list entry index
    // drawn at that point.
    fn get_entry_index(&self, p: Point) -> Option<u32> {
        if self.rect.get().contains(p) {
            let mut current_y = 0;
            let x = self.rect.get().x;
            let y = self.rect.get().y;
            let width = self.rect.get().width;
            let scroll = self.v_scroll.get();

            for (i, entry) in self.entries.borrow().iter().enumerate() {
                if Rect::new(x, y+current_y-scroll, width, entry.height.get()).contains(p) {
                    return Some(i as u32)
                }
                current_y += entry.height.get() as i32
            }
        }

        None
    }

    pub fn scroll(&self, y: i32) {
        let mut set_to = self.v_scroll.get() - y;
        if set_to < 0 {
            set_to = 0;
        } else if self.rect.get().height as i32 + set_to > self.current_height.get() as i32 {
            set_to = self.v_scroll.get() as i32;
        }
        self.v_scroll.set(set_to);
    }

    fn change_selection(&self, i: u32) {
        match self.selected.get() {
            Some(i) => {
                match self.entries.borrow().get(i as usize) {
                    Some(entry) => {
                        entry.highlighted.set(false);
                    },
                    None => {},
                }
            },
            _ => {},
        }

        if let Some(entry) = self.entries.borrow().get(i as usize) {
            entry.highlighted.set(true);
            self.selected.set(Some(i));

            let mut y = 0;

            for e in self.entries.borrow().index(0..(i as usize)) {
                y += e.height.get();
            }

            let v_scroll = self.v_scroll.get();

            if y < v_scroll as u32 {
                self.scroll(y as i32 - v_scroll);
            } else if (y + entry.height.get() as u32) > (v_scroll as u32 + self.rect.get().height) {
                self.scroll((y + entry.height.get()) as i32 - (v_scroll + self.rect.get().height as i32));
            }
        }
    }
}

impl Widget for List {
    fn rect(&self) -> &Cell<Rect> {
        &self.rect
    }

    fn draw(&self, renderer: &mut Renderer, _focused: bool) {
        let mut current_y = 0;
        let x = self.rect.get().x;
        let y = self.rect.get().y;
        let width = self.rect.get().width;
        let height = self.rect.get().height;

        let mut target = orbimage::Image::new(width, height);
        target.set(WINDOW_BACKGROUND);

        for entry in self.entries.borrow().iter() {
            let mut image = orbimage::Image::new(width, entry.height.get());

            if entry.highlighted.get() {
                image.set(entry.highlight.get());
            } else {
                image.set(ITEM_BACKGROUND);
            }

            for widget in entry.widgets().borrow().iter() {
                widget.draw(&mut image, false)
            }

            let image = image.data();
            target.image(x, current_y-self.v_scroll.get(), width, entry.height.get(), &image);

            current_y += entry.height.get() as i32
        }
        let target = target.data();
        renderer.image(x, y, width, height, &target)
    }

    fn event(&self, event: Event, focused: bool, redraw: &mut bool) -> bool {
        match event {
            Event::Mouse { point, left_button, .. } => {
                let mut click = false;

                let rect = self.rect.get();
                if rect.contains(point) {
                    if left_button {
                        if self.pressed.check_set(true) {
                            *redraw = true;
                        }
                    } else {
                        if self.pressed.check_set(false) {
                            click = true;
                            *redraw = true;
                        }
                    }
                } else {
                    if !left_button {
                        if self.pressed.check_set(false) {
                            *redraw = true;
                        }
                    }
                }

                if let Some(i) = self.get_entry_index(point) {
                    if click {
                        if let Some(entry) = self.entries.borrow().get(i as usize) {
                            entry.emit_click(point);
                        }
                    }

                    match self.selected.get() {
                        None => {
                            self.change_selection(i);
                            *redraw = true;
                        },
                        Some(selected) => {
                            if selected != i {
                                self.change_selection(i);
                                *redraw = true;
                            }
                        },
                    }
                }
            },
            Event::UpArrow => {
                match self.selected.get() {
                    None => {
                        self.change_selection(0);
                        *redraw = true;
                    },
                    Some(i) => {
                        if i > 0 {
                            self.change_selection(i - 1);
                            *redraw = true;
                        }
                    }
                }
            },
            Event::DownArrow => {
                match self.selected.get() {
                    None => {
                        self.change_selection(0);
                        *redraw = true;
                    },
                    Some(i) => {
                        if i < self.entries.borrow().len() as u32 - 1 {
                            self.change_selection(i + 1);
                            *redraw = true;
                        }
                    }
                }
            },
            Event::Home => {
                self.change_selection(0);
                *redraw = true
            },
            Event::End => {
                self.change_selection(self.entries.borrow().len() as u32 - 1);
                *redraw = true
            },
            Event::Enter => {
                match self.selected.get() {
                    Some(i) => {
                        match self.entries.borrow().get(i as usize) {
                            Some(entry) => {
                                entry.emit_click(Point { x: 0, y: 0});
                            },
                            None => {},
                        }
                    },
                    _ => {},
                }
            },
            Event::Scroll { y, .. } => {
                self.scroll(y * 2);
                *redraw = true;
            },
            _ => {}
        }
        focused
    }
}

impl Place for List {}

<|endoftext|>


<commit_before>#![deny(unused_import_braces,
        unused_comparisons, unused_must_use,
        unused_variables, non_shorthand_field_patterns,
        unreachable_code)]

extern crate trie;
extern crate sputnikvm;
extern crate sha3;
extern crate block;
extern crate rlp;

use trie::{Database, DatabaseOwned, MemoryDatabase};

use sputnikvm::{H256, U256, M256};
use sputnikvm::vm::{self, ValidTransaction, HeaderParams, Memory, TransactionVM, VM,
                    AccountCommitment, Patch, SeqMemory};
use sputnikvm::vm::errors::RequireError;
use trie::{Trie, DatabaseGuard};
use block::Account;
use sha3::{Digest, Keccak256};
use std::collections::HashMap;
use std::cmp::min;

pub struct Stateful<G, D> {
    database: D,
    code_hashes: G,
    root: H256,
}

impl<G, D> Stateful<G, D> {
    pub fn new(database: D, code_hashes: G, root: H256) -> Self {
        Self {
            database,
            code_hashes,
            root
        }
    }
}

impl<G: Default, D: Default> Default for Stateful<G, D> {
    fn default() -> Self {
        Self {
            database: D::default(),
            code_hashes: G::default(),
            root: MemoryDatabase::new().create_empty().root(),
        }
    }
}

impl<G: DatabaseGuard, D: DatabaseOwned> Stateful<G, D> {
    fn is_empty_hash(hash: H256) -> bool {
        hash == H256::from(Keccak256::digest(&[]).as_slice())
    }

    pub fn call<M: Memory + Default>(
        &self, transaction: ValidTransaction, block: HeaderParams,
        patch: &'static Patch, most_recent_block_hashes: &[H256]
    ) -> TransactionVM<M> {
        assert!(U256::from(most_recent_block_hashes.len()) >=
                min(block.number, U256::from(256)));

        let mut vm = TransactionVM::new(transaction, block.clone(), patch);
        let state = self.database.create_trie(self.root);

        loop {
            match vm.fire() {
                Ok(()) => break,
                Err(RequireError::Account(address)) => {
                    let account: Option<Account> = state.get(&address);

                    match account {
                        Some(account) => {
                            let code = if Self::is_empty_hash(account.code_hash) {
                                Vec::new()
                            } else {
                                self.code_hashes.get(account.code_hash).unwrap()
                            };

                            vm.commit_account(AccountCommitment::Full {
                                nonce: account.nonce,
                                address: address,
                                balance: account.balance,
                                code: code,
                            }).unwrap();
                        },
                        None => {
                            vm.commit_account(AccountCommitment::Nonexist(address)).unwrap();
                        },
                    }
                },
                Err(RequireError::AccountCode(address)) => {
                    let account: Option<Account> = state.get(&address);

                    match account {
                        Some(account) => {
                            let code = if Self::is_empty_hash(account.code_hash) {
                                Vec::new()
                            } else {
                                self.code_hashes.get(account.code_hash).unwrap()
                            };

                            vm.commit_account(AccountCommitment::Code {
                                address: address,
                                code: code,
                            }).unwrap();
                        },
                        None => {
                            vm.commit_account(AccountCommitment::Nonexist(address)).unwrap();
                        },
                    }
                },
                Err(RequireError::AccountStorage(address, index)) => {
                    let account: Option<Account> = state.get(&address);

                    match account {
                        Some(account) => {
                            let storage = self.database.create_trie(account.storage_root);
                            let value = storage.get(&index).unwrap_or(M256::zero());

                            vm.commit_account(AccountCommitment::Storage {
                                address: address,
                                index, value
                            }).unwrap();
                        },
                        None => {
                            vm.commit_account(AccountCommitment::Nonexist(address)).unwrap();
                        },
                    }
                },
                Err(RequireError::Blockhash(number)) => {
                    let index = (block.number - number).as_usize();
                    vm.commit_blockhash(number, most_recent_block_hashes[index]).unwrap();
                },
            }
        }

        vm
    }

    pub fn transit(
        &mut self, accounts: &[vm::Account]
    ) {
        let mut state = self.database.create_trie(self.root);

        for account in accounts {
            match account.clone() {
                vm::Account::Full {
                    nonce, address, balance, changing_storage, code
                } => {
                    let changing_storage: HashMap<U256, M256> = changing_storage.into();

                    let mut account: Account = state.get(&address).unwrap();

                    let mut storage_trie = self.database.create_trie(account.storage_root);
                    for (key, value) in changing_storage {
                        storage_trie.insert(key, value);
                    }

                    account.balance = balance;
                    account.nonce = nonce;
                    account.storage_root = storage_trie.root();
                    assert!(account.code_hash == H256::from(Keccak256::digest(&code).as_slice()));

                    state.insert_raw(Keccak256::digest(&address).as_slice().into(),
                                     rlp::encode(&account).to_vec());
                },
                vm::Account::IncreaseBalance(address, value) => {
                    let mut account: Account = state.get(&address).unwrap();

                    account.balance = account.balance + value;

                    state.insert_raw(Keccak256::digest(&address).as_slice().into(),
                                     rlp::encode(&account).to_vec());
                },
                vm::Account::DecreaseBalance(address, value) => {
                    let mut account: Account = state.get(&address).unwrap();

                    account.balance = account.balance - value;

                    state.insert_raw(Keccak256::digest(&address).as_slice().into(),
                                     rlp::encode(&account).to_vec());
                },
                vm::Account::Create {
                    nonce, address, balance, storage, code, exists
                } => {
                    if !exists {
                        state.remove_raw(Keccak256::digest(&address).as_slice());
                    } else {
                        let storage: HashMap<U256, M256> = storage.into();

                        let mut storage_trie = self.database.create_empty();
                        for (key, value) in storage {
                            storage_trie.insert(key, value);
                        }

                        let code_hash = H256::from(Keccak256::digest(&code).as_slice());
                        self.code_hashes.set(code_hash, code);

                        let account = Account {
                            nonce: nonce,
                            balance: balance,
                            storage_root: storage_trie.root(),
                            code_hash
                        };

                        state.insert_raw(Keccak256::digest(&address).as_slice().into(),
                                         rlp::encode(&account).to_vec());
                    }
                },
            }
        }

        self.root = state.root();
    }

    pub fn execute<M: Memory + Default>(
        &mut self, transaction: ValidTransaction, block: HeaderParams,
        patch: &'static Patch, most_recent_block_hashes: &[H256]
    ) -> TransactionVM<M> {
        let vm = self.call(transaction, block, patch, most_recent_block_hashes);
        let mut accounts = Vec::new();
        for account in vm.accounts() {
            accounts.push(account.clone());
        }
        self.transit(&accounts);
        vm
    }

    pub fn root(&self) -> H256 {
        self.root
    }
}

pub type MemoryStateful = Stateful<HashMap<H256, Vec<u8>>, MemoryDatabase>;
<commit_msg>stateful: use fixed secure trie for account and storage<commit_after>#![deny(unused_import_braces,
        unused_comparisons, unused_must_use,
        unused_variables, non_shorthand_field_patterns,
        unreachable_code)]

extern crate trie;
extern crate sputnikvm;
extern crate sha3;
extern crate block;
extern crate rlp;

use sputnikvm::{H256, U256, M256, Address};
use sputnikvm::vm::{self, ValidTransaction, HeaderParams, Memory, TransactionVM, VM,
                    AccountCommitment, Patch, SeqMemory};
use sputnikvm::vm::errors::RequireError;
use sha3::{Keccak256, Digest};
use trie::{Trie, SecureTrie, FixedSecureTrie, DatabaseGuard, MemoryDatabase, MemoryDatabaseGuard, Database, DatabaseOwned};
use block::Account;
use std::collections::HashMap;
use std::cmp::min;

pub struct Stateful<G, D> {
    database: D,
    code_hashes: G,
    root: H256,
}

impl<G, D> Stateful<G, D> {
    pub fn new(database: D, code_hashes: G, root: H256) -> Self {
        Self {
            database,
            code_hashes,
            root
        }
    }
}

impl<G: Default, D: Default> Default for Stateful<G, D> {
    fn default() -> Self {
        Self {
            database: D::default(),
            code_hashes: G::default(),
            root: MemoryDatabase::new().create_empty().root(),
        }
    }
}

impl<G: DatabaseGuard, D: DatabaseOwned> Stateful<G, D> {
    fn is_empty_hash(hash: H256) -> bool {
        hash == H256::from(Keccak256::digest(&[]).as_slice())
    }

    pub fn call<M: Memory + Default>(
        &self, transaction: ValidTransaction, block: HeaderParams,
        patch: &'static Patch, most_recent_block_hashes: &[H256]
    ) -> TransactionVM<M> {
        assert!(U256::from(most_recent_block_hashes.len()) >=
                min(block.number, U256::from(256)));

        let mut vm = TransactionVM::new(transaction, block.clone(), patch);
        let state = self.database.create_fixed_secure_trie(self.root);

        loop {
            match vm.fire() {
                Ok(()) => break,
                Err(RequireError::Account(address)) => {
                    let account: Option<Account> = state.get(&address);

                    match account {
                        Some(account) => {
                            let code = if Self::is_empty_hash(account.code_hash) {
                                Vec::new()
                            } else {
                                self.code_hashes.get(account.code_hash).unwrap()
                            };

                            vm.commit_account(AccountCommitment::Full {
                                nonce: account.nonce,
                                address: address,
                                balance: account.balance,
                                code: code,
                            }).unwrap();
                        },
                        None => {
                            vm.commit_account(AccountCommitment::Nonexist(address)).unwrap();
                        },
                    }
                },
                Err(RequireError::AccountCode(address)) => {
                    let account: Option<Account> = state.get(&address);

                    match account {
                        Some(account) => {
                            let code = if Self::is_empty_hash(account.code_hash) {
                                Vec::new()
                            } else {
                                self.code_hashes.get(account.code_hash).unwrap()
                            };

                            vm.commit_account(AccountCommitment::Code {
                                address: address,
                                code: code,
                            }).unwrap();
                        },
                        None => {
                            vm.commit_account(AccountCommitment::Nonexist(address)).unwrap();
                        },
                    }
                },
                Err(RequireError::AccountStorage(address, index)) => {
                    let account: Option<Account> = state.get(&address);

                    match account {
                        Some(account) => {
                            let storage = self.database.create_fixed_secure_trie(account.storage_root);
                            let value = storage.get(&H256::from(index)).unwrap_or(M256::zero());

                            vm.commit_account(AccountCommitment::Storage {
                                address: address,
                                index, value
                            }).unwrap();
                        },
                        None => {
                            vm.commit_account(AccountCommitment::Nonexist(address)).unwrap();
                        },
                    }
                },
                Err(RequireError::Blockhash(number)) => {
                    let index = (block.number - number).as_usize();
                    vm.commit_blockhash(number, most_recent_block_hashes[index]).unwrap();
                },
            }
        }

        vm
    }

    pub fn transit(
        &mut self, accounts: &[vm::Account]
    ) {
        let mut state = self.database.create_fixed_secure_trie(self.root);

        for account in accounts {
            match account.clone() {
                vm::Account::Full {
                    nonce, address, balance, changing_storage, code
                } => {
                    let changing_storage: HashMap<U256, M256> = changing_storage.into();

                    let mut account: Account = state.get(&address).unwrap();

                    let mut storage_trie = self.database.create_fixed_secure_trie(account.storage_root);
                    for (key, value) in changing_storage {
                        storage_trie.insert(H256::from(key), value);
                    }

                    account.balance = balance;
                    account.nonce = nonce;
                    account.storage_root = storage_trie.root();
                    assert!(account.code_hash == H256::from(Keccak256::digest(&code).as_slice()));

                    state.insert(address, account);
                },
                vm::Account::IncreaseBalance(address, value) => {
                    let mut account: Account = state.get(&address).unwrap();

                    account.balance = account.balance + value;

                    state.insert(address, account);
                },
                vm::Account::DecreaseBalance(address, value) => {
                    let mut account: Account = state.get(&address).unwrap();

                    account.balance = account.balance - value;

                    state.insert(address, account);
                },
                vm::Account::Create {
                    nonce, address, balance, storage, code, exists
                } => {
                    if !exists {
                        state.remove(&address);
                    } else {
                        let storage: HashMap<U256, M256> = storage.into();

                        let mut storage_trie = self.database.create_fixed_secure_empty();
                        for (key, value) in storage {
                            storage_trie.insert(H256::from(key), value);
                        }

                        let code_hash = H256::from(Keccak256::digest(&code).as_slice());
                        self.code_hashes.set(code_hash, code);

                        let account = Account {
                            nonce: nonce,
                            balance: balance,
                            storage_root: storage_trie.root(),
                            code_hash
                        };

                        state.insert(address, account);
                    }
                },
            }
        }

        self.root = state.root();
    }

    pub fn execute<M: Memory + Default>(
        &mut self, transaction: ValidTransaction, block: HeaderParams,
        patch: &'static Patch, most_recent_block_hashes: &[H256]
    ) -> TransactionVM<M> {
        let vm = self.call(transaction, block, patch, most_recent_block_hashes);
        let mut accounts = Vec::new();
        for account in vm.accounts() {
            accounts.push(account.clone());
        }
        self.transit(&accounts);
        vm
    }

    pub fn root(&self) -> H256 {
        self.root
    }

    pub fn state<'a>(&'a self) -> FixedSecureTrie<<D as Database<'a>>::Guard, Address, Account> {
        self.database.create_fixed_secure_trie::<Address, Account>(self.root())
    }
}

pub type MemoryStateful = Stateful<HashMap<H256, Vec<u8>>, MemoryDatabase>;
<|endoftext|>


<commit_before>use failure::{self, prelude::*};
use std::{
    ffi::OsStr,
    fmt,
    process::{Command, Stdio},
};

#[derive(Clone)]
pub struct Instance {
    short_hash: String,
    ip: String,
    ac_port: u32,
}

impl Instance {
    pub fn new(short_hash: String, ip: String, ac_port: u32) -> Instance {
        Instance {
            short_hash,
            ip,
            ac_port,
        }
    }

    pub fn run_cmd_tee_err<I, S>(&self, args: I) -> failure::Result<()>
    where
        I: IntoIterator<Item = S>,
        S: AsRef<OsStr>,
    {
        self.run_cmd_inner(false, args)
    }

    pub fn run_cmd<I, S>(&self, args: I) -> failure::Result<()>
    where
        I: IntoIterator<Item = S>,
        S: AsRef<OsStr>,
    {
        self.run_cmd_inner(true, args)
    }

    pub fn run_cmd_inner<I, S>(&self, no_std_err: bool, args: I) -> failure::Result<()>
    where
        I: IntoIterator<Item = S>,
        S: AsRef<OsStr>,
    {
        let ssh_dest = format!("ec2-user@{}", self.ip);
        let ssh_args = vec![
            "-i",
            "/libra_rsa",
            "-oStrictHostKeyChecking=no",
            ssh_dest.as_str(),
        ];
        let mut ssh_cmd = Command::new("ssh");
        ssh_cmd.args(ssh_args).args(args);
        if no_std_err {
            ssh_cmd.stderr(Stdio::null());
        }
        let status = ssh_cmd.status()?;
        ensure!(
            status.success(),
            "Failed with code {}",
            status.code().unwrap_or(-1)
        );
        Ok(())
    }

    pub fn short_hash(&self) -> &String {
        &self.short_hash
    }

    pub fn ip(&self) -> &String {
        &self.ip
    }

    pub fn ac_port(&self) -> u32 {
        self.ac_port
    }
}

impl fmt::Display for Instance {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "{}({})", self.short_hash, self.ip)
    }
}
<commit_msg>[cluster-test] Set timeout for running ssh<commit_after>use failure::{self, prelude::*};
use std::{
    ffi::OsStr,
    fmt,
    process::{Command, Stdio},
};

#[derive(Clone)]
pub struct Instance {
    short_hash: String,
    ip: String,
    ac_port: u32,
}

impl Instance {
    pub fn new(short_hash: String, ip: String, ac_port: u32) -> Instance {
        Instance {
            short_hash,
            ip,
            ac_port,
        }
    }

    pub fn run_cmd_tee_err<I, S>(&self, args: I) -> failure::Result<()>
    where
        I: IntoIterator<Item = S>,
        S: AsRef<OsStr>,
    {
        self.run_cmd_inner(false, args)
    }

    pub fn run_cmd<I, S>(&self, args: I) -> failure::Result<()>
    where
        I: IntoIterator<Item = S>,
        S: AsRef<OsStr>,
    {
        self.run_cmd_inner(true, args)
    }

    pub fn run_cmd_inner<I, S>(&self, no_std_err: bool, args: I) -> failure::Result<()>
    where
        I: IntoIterator<Item = S>,
        S: AsRef<OsStr>,
    {
        let ssh_dest = format!("ec2-user@{}", self.ip);
        let ssh_args = vec![
            "ssh",
            "-i",
            "/libra_rsa",
            "-oStrictHostKeyChecking=no",
            ssh_dest.as_str(),
        ];
        let mut ssh_cmd = Command::new("timeout");
        ssh_cmd.arg("15").args(ssh_args).args(args);
        if no_std_err {
            ssh_cmd.stderr(Stdio::null());
        }
        let status = ssh_cmd.status()?;
        ensure!(
            status.success(),
            "Failed with code {}",
            status.code().unwrap_or(-1)
        );
        Ok(())
    }

    pub fn short_hash(&self) -> &String {
        &self.short_hash
    }

    pub fn ip(&self) -> &String {
        &self.ip
    }

    pub fn ac_port(&self) -> u32 {
        self.ac_port
    }
}

impl fmt::Display for Instance {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "{}({})", self.short_hash, self.ip)
    }
}
<|endoftext|>


<commit_before>#![feature(test)]

extern crate test;
extern crate bf;

#[cfg(feature = "jit")]
mod jit_only {
    use bf::ast;
    use bf::rle;
    use bf::peephole;
    use bf::jit;

    use bf::traits::Interpretable;
    use bf::test_helpers;

    use test::Bencher;

    #[bench]
    fn compile_factor(b: &mut Bencher) {
        let program = ast::parse_program(test_helpers::FACTOR_SRC).unwrap();

        b.iter(|| {
            let program = rle::compile(&program);
            let program = peephole::compile(&program);
            jit::compile(&program, true)
        });
    }

    #[bench]
    fn interpret_factor_million(b: &mut Bencher) {
        let program = ast::parse_program(test_helpers::FACTOR_SRC).unwrap();
        let program = rle::compile(&program);
        let program = peephole::compile(&program);
        let program = jit::compile(&program, true);

        b.iter(|| {
            program.interpret_memory(None, b"1000000\n").unwrap()
        });
    }

    #[bench]
    fn interpret_factor_million_unchecked(b: &mut Bencher) {
        let program = ast::parse_program(test_helpers::FACTOR_SRC).unwrap();
        let program = rle::compile(&program);
        let program = peephole::compile(&program);
        let program = jit::compile(&program, false);

        b.iter(|| {
            program.interpret_memory(None, b"1000000\n").unwrap()
        });
    }
}<commit_msg>Renamed JIT benchmarks from interpret_* to run_*.<commit_after>#![feature(test)]

extern crate test;
extern crate bf;

#[cfg(feature = "jit")]
mod jit_only {
    use bf::ast;
    use bf::rle;
    use bf::peephole;
    use bf::jit;

    use bf::traits::Interpretable;
    use bf::test_helpers;

    use test::Bencher;

    #[bench]
    fn compile_factor(b: &mut Bencher) {
        let program = ast::parse_program(test_helpers::FACTOR_SRC).unwrap();

        b.iter(|| {
            let program = rle::compile(&program);
            let program = peephole::compile(&program);
            jit::compile(&program, true)
        });
    }

    #[bench]
    fn run_factor_million(b: &mut Bencher) {
        let program = ast::parse_program(test_helpers::FACTOR_SRC).unwrap();
        let program = rle::compile(&program);
        let program = peephole::compile(&program);
        let program = jit::compile(&program, true);

        b.iter(|| {
            program.interpret_memory(None, b"1000000\n").unwrap()
        });
    }

    #[bench]
    fn run_factor_million_unchecked(b: &mut Bencher) {
        let program = ast::parse_program(test_helpers::FACTOR_SRC).unwrap();
        let program = rle::compile(&program);
        let program = peephole::compile(&program);
        let program = jit::compile(&program, false);

        b.iter(|| {
            program.interpret_memory(None, b"1000000\n").unwrap()
        });
    }
}<|endoftext|>


<commit_before>extern crate simple_csv;

use std::env;
use std::fs::File;
use std::io::BufReader;
use std::str::FromStr;
use simple_csv::{SimpleCsvWriter, SimpleCsvReader};

fn main(){
    let args : Vec<String> = env::args().collect();
    let alpha = f64::from_str(&args[1]).expect("first argument should be the threshold");

    let f = File::open("assets/filter.csv").unwrap();
    let buf = BufReader::new(f);
    let reader = SimpleCsvReader::new(buf);

    let raw: Vec<(f64, f64)> = reader
        .map (|r| r.unwrap())
        .map(data)
        .collect();

    let mut result: Vec<(f64, f64, f64)> = vec!();
    let mut smoothed: Option<(f64, f64)> = None;
    for candidate in raw {
        match smoothed {
            Some(previous) => {
                let next = alpha * candidate.1 + (1f64 - alpha) * previous.1;
                result.push((candidate.0, next, candidate.1 - next));
                smoothed = Some((candidate.0, next));
            }

            None => {
                smoothed = Some(candidate)
            }
        }
    }

    let o = File::create("assets/detrend.csv").unwrap();
    let mut writer = SimpleCsvWriter::new(o);

    for (time, trend, difference) in result {
        writer.write(
            &vec!(time.to_string(), trend.to_string(), difference.to_string())
        ).unwrap();
    }
}

fn data(row: Vec<String>) -> (f64, f64) {
    let iter = row.iter();

    let raw: Vec<f64> = iter
        .map(|s| f64::from_str(s).unwrap())
        .collect();

    (raw[0], raw[1])
}
<commit_msg>Create a struct to contain detrend data<commit_after>extern crate simple_csv;

use std::env;
use std::fs::File;
use std::io::BufReader;
use std::str::FromStr;
use simple_csv::{SimpleCsvWriter, SimpleCsvReader};

fn main(){
    let args : Vec<String> = env::args().collect();
    let alpha = f64::from_str(&args[1]).expect("first argument should be the threshold");

    let f = File::open("assets/filter.csv").unwrap();
    let buf = BufReader::new(f);
    let reader = SimpleCsvReader::new(buf);

    let raw: Vec<(f64, f64)> = reader
        .map (|r| r.unwrap())
        .map(data)
        .collect();

    let mut sequence: Vec<DetrendData> = vec!();
    let mut data: Option<DetrendData> = None;
    for candidate in raw {
        match data{
            Some(previous) => {
                let next = previous.next(candidate, alpha);
                sequence.push(previous);
                data = Some(next);
            }

            None => {
                data = Some(DetrendData::initial(candidate))

            }
        }
    }

    let o = File::create("assets/detrend.csv").unwrap();
    let mut writer = SimpleCsvWriter::new(o);

    for data in sequence {
        writer.write(
            &data.as_vec()
        ).unwrap();
    }
}

fn data(row: Vec<String>) -> (f64, f64) {
    let iter = row.iter();

    let raw: Vec<f64> = iter
        .map(|s| f64::from_str(s).unwrap())
        .collect();

    (raw[0], raw[1])
}

struct DetrendData {
    time: f64,
    brightness: f64,
    trend: f64,
    difference: f64,
}

impl DetrendData {
    fn initial((time, brightness): (f64,f64)) -> DetrendData {
        DetrendData {
            time: time,
            brightness: brightness,
            trend: brightness,
            difference: 0f64,
        }
    }

    fn next(&self, (time, brightness): (f64, f64), alpha: f64) -> DetrendData {
        let trend = alpha * brightness + (1f64 - alpha) * self.trend;
        DetrendData {
            time: time,
            brightness: brightness,
            trend: trend,
            difference: brightness - trend,
        }

    }

    fn as_vec(&self) -> Vec<String> {
        vec!(
            self.time.to_string(),
            self.brightness.to_string(),
            self.trend.to_string(),
            self.difference.to_string(),
        )
    }
}
<|endoftext|>


<commit_before>use env::Env;
use library;
use analysis::rust_type::Result;

pub fn ffi_type(env: &Env, type_id: library::TypeId) -> Result {
    use library::Type::*;
    use library::Fundamental::*;
    let type_ = env.library.type_(type_id);
    let ffi_type = match type_ {
        &Fundamental(fund) => {
            let ok = |s: &str| Ok(s.into());
            let err = |s: &str| Err(s.into());
            match fund {
                None => err("()"),
                Boolean => ok("gboolean"),
                Int8 => ok("gint8"),
                UInt8 => ok("guint8"),
                Int16 => ok("gint16"),
                UInt16 => ok("guint16"),
                Int32 => ok("gint32"),
                UInt32 => ok("guint32"),
                Int64 => ok("gint64"),
                UInt64 => ok("guint64"),

                Int => ok("gint"),      //maybe dependent on target system
                UInt => ok("guint"),     //maybe dependent on target system

                Float => ok("gfloat"),
                Double => ok("gdouble"),

                Utf8 => ok("*const c_char"),

                Type => ok("GType"),
                Unsupported => err("Unsupported"),
                _ => err(&format!("Fundamental: {:?}", fund)),
            }
        },

        &Enumeration(ref enum_) => Ok(enum_.glib_type_name.clone()),
        &Interface(ref interface) => Ok(format!("*mut {}", interface.glib_type_name)),
        &Class(ref klass) => Ok(format!("*mut {}", klass.glib_type_name)),
        _ => Err(format!("Unknown rust type: {:?}", type_.get_name() )),
        //TODO: check usage library::Type::get_name() when no _ in this
    };
    ffi_type
}
<commit_msg>Add prefix for external types<commit_after>use analysis::rust_type::Result;
use env::Env;
use gobjects::GStatus;
use library;
use nameutil::module_name;

pub fn ffi_type(env: &Env, type_id: library::TypeId) -> Result {
    use library::Type::*;
    use library::Fundamental::*;
    let type_ = env.library.type_(type_id);
    match type_ {
        &Fundamental(fund) => {
            let ok = |s: &str| Ok(s.into());
            let err = |s: &str| Err(s.into());
            match fund {
                None => err("()"),
                Boolean => ok("gboolean"),
                Int8 => ok("gint8"),
                UInt8 => ok("guint8"),
                Int16 => ok("gint16"),
                UInt16 => ok("guint16"),
                Int32 => ok("gint32"),
                UInt32 => ok("guint32"),
                Int64 => ok("gint64"),
                UInt64 => ok("guint64"),

                Int => ok("gint"),      //maybe dependent on target system
                UInt => ok("guint"),     //maybe dependent on target system

                Float => ok("gfloat"),
                Double => ok("gdouble"),

                Utf8 => ok("*const c_char"),

                Type => ok("GType"),
                Unsupported => err("Unsupported"),
                _ => err(&format!("Fundamental: {:?}", fund)),
            }
        },

        &Enumeration(ref enum_) => Ok(enum_.glib_type_name.clone()),
        &Interface(ref interface) => to_mut_ptr(fix_external_name(env, type_id, &interface.glib_type_name)),
        &Class(ref klass) => to_mut_ptr(fix_external_name(env, type_id, &klass.glib_type_name)),
        _ => Err(format!("Unknown rust type: {:?}", type_.get_name() )),
        //TODO: check usage library::Type::get_name() when no _ in this
    }
}

fn fix_external_name(env: &Env, type_id: library::TypeId, name: &str) -> Result {
    if type_id.ns_id == library::MAIN_NAMESPACE || type_id.ns_id == library::INTERNAL_NAMESPACE {
        Ok(name.into())
    } else {
        let name_with_prefix = format!("{}_ffi::{}",
            module_name(&env.library.namespace(type_id.ns_id).name), name);
        if env.type_status(&type_id.full_name(&env.library)) == GStatus::Ignore {
            Err(name_with_prefix.into())
        } else {
            Ok(name_with_prefix)
        }
    }
}

fn to_mut_ptr(res: Result) -> Result {
    match res {
        Ok(s) => Ok(format!("*mut {}", s)),
        Err(s) => Err(format!("*mut {}", s)),
    }
}
<|endoftext|>


<commit_before>use std::collections::HashSet;
use super::{Nearness, Basics};
use {RowId, ColumnId, Column, Mutator};
use std::marker::PhantomData;

struct Detector<B: Basics> {
  _marker: PhantomData<B>,
}
impl<B: Basics> Column for Detector<B> {
  type FieldType = HashSet <RowId>;
  fn column_id() -> ColumnId {
    ColumnId(B::nearness_column_id().0 ^ 0xdaa7e18546759b65)
  }
}

pub fn insert<B: Basics, M: Mutator<B::StewardBasics>>(mutator: &mut M,
                                                       who: RowId,
                                                       me: B::DetectorId) {
  let my_row = RowId::new(&me);
  let mut members = mutator.get::<Detector<B>>(my_row).unwrap().clone();
  for member in members.iter() {
    let (id, contents) = Nearness::new(who, member.clone(), me);
    mutator.set::<Nearness<B>>(id, Some(contents));
  }
  members.insert(who);
  mutator.set::<Detector<B>>(my_row, Some(members));
}

pub fn erase<B: Basics, M: Mutator<B::StewardBasics>>(mutator: &mut M,
                                                      who: RowId,
                                                      me: B::DetectorId) {
  let my_row = RowId::new(&me);
  let mut members = mutator.get::<Detector<B>>(my_row).unwrap().clone();
  members.remove(&who);
  for member in members.iter() {
    let (id,_) = Nearness::<B>::new(who, member.clone(), me);
    mutator.set::<Nearness<B>>(id, None);
  }
  mutator.set::<Detector<B>>(my_row, Some(members));
}
<commit_msg>Fixed bug<commit_after>use std::collections::HashSet;
use super::{Nearness, Basics};
use {RowId, ColumnId, Column, Mutator};
use std::marker::PhantomData;

struct Detector<B: Basics> {
  _marker: PhantomData<B>,
}
impl<B: Basics> Column for Detector<B> {
  type FieldType = HashSet <RowId>;
  fn column_id() -> ColumnId {
    ColumnId(B::nearness_column_id().0 ^ 0xdaa7e18546759b65)
  }
}

pub fn insert<B: Basics, M: Mutator<B::StewardBasics>>(mutator: &mut M,
                                                       who: RowId,
                                                       me: B::DetectorId) {
  let my_row = RowId::new(&me);
  let mut members = mutator.get::<Detector<B>>(my_row).cloned().unwrap_or (HashSet::new());
  for member in members.iter() {
    let (id, contents) = Nearness::new(who, member.clone(), me);
    mutator.set::<Nearness<B>>(id, Some(contents));
  }
  members.insert(who);
  mutator.set::<Detector<B>>(my_row, Some(members));
}

pub fn erase<B: Basics, M: Mutator<B::StewardBasics>>(mutator: &mut M,
                                                      who: RowId,
                                                      me: B::DetectorId) {
  let my_row = RowId::new(&me);
  let mut members = mutator.get::<Detector<B>>(my_row).expect("erasing an element when there are no elements").clone();
  members.remove(&who);
  for member in members.iter() {
    let (id,_) = Nearness::<B>::new(who, member.clone(), me);
    mutator.set::<Nearness<B>>(id, None);
  }
  mutator.set::<Detector<B>>(my_row, if members.is_empty() {None} else { Some(members)});
}
<|endoftext|>


<commit_before>//! A generic event loop for games and interactive applications

#![deny(missing_docs)]
#![deny(missing_copy_implementations)]

extern crate window;
extern crate input;
extern crate viewport;

use std::thread::sleep;
use std::time::{Duration, Instant};
use std::cmp;
use window::Window;
use input::{ AfterRenderArgs, Event, IdleArgs, RenderArgs, UpdateArgs };

/// A trait for create event iterator from window.
pub trait Events {
    /// Creates event iterator from window.
    fn events(&self) -> WindowEvents;
}

impl<W> Events for W where W: Window {
    fn events(&self) -> WindowEvents {
        WindowEvents::new()
    }
}

/// Tells whether last emitted event was idle or not.
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
enum Idle {
    No,
    Yes
}

// Stores the update state right after sleep.
// This is used to avoid logic error when changing settings
// in the event loop followed by an update.
#[derive(Copy, Clone, Debug)]
struct UpdateState {
    dt_update_in_ns: u64,
    dt: f64,
}

#[derive(Copy, Clone, Debug)]
enum State {
    Render,
    SwapBuffers,
    UpdateLoop(Idle),
    HandleEvents(UpdateState),
    Update(UpdateState),
}

/// Methods implements for event loop settings.
pub trait EventLoop: Sized {
    /// The number of updates per second
    ///
    /// This is the fixed update rate on average over time.
    /// If the event loop lags, it will try to catch up.
    fn set_ups(&mut self, frames: u64);

    /// The number of updates per second
    ///
    /// This is the fixed update rate on average over time.
    /// If the event loop lags, it will try to catch up.
    fn ups(mut self, frames: u64) -> Self {
        self.set_ups(frames);
        self
    }

    /// The maximum number of frames per second
    ///
    /// The frame rate can be lower because the
    /// next frame is always scheduled from the previous frame.
    /// This causes the frames to "slip" over time.
    fn set_max_fps(&mut self, frames: u64);

    /// The maximum number of frames per second
    ///
    /// The frame rate can be lower because the
    /// next frame is always scheduled from the previous frame.
    /// This causes the frames to "slip" over time.
    fn max_fps(mut self, frames: u64) -> Self {
        self.set_max_fps(frames);
        self
    }

    /// Enable or disable automatic swapping of buffers.
    fn set_swap_buffers(&mut self, enable: bool);

    /// Enable or disable automatic swapping of buffers.
    fn swap_buffers(mut self, enable: bool) -> Self {
        self.set_swap_buffers(enable);
        self
    }

    /// Enable or disable benchmark mode.
    /// When enabled, it will render and update without sleep and ignore input.
    /// Used to test performance by playing through as fast as possible.
    fn set_bench_mode(&mut self, enable: bool);

    /// Enable or disable benchmark mode.
    /// When enabled, it will render and update without sleep and ignore input.
    /// Used to test performance by playing through as fast as possible.
    fn bench_mode(mut self, enable: bool) -> Self {
        self.set_bench_mode(enable);
        self
    }
}

/// An event loop iterator
///
/// *Warning: Because the iterator polls events from the window back-end,
/// it must be used on the same thread as the window back-end (usually main thread),
/// unless the window back-end supports multi-thread event polling.*
#[derive(Copy, Clone)]
pub struct WindowEvents {
    state: State,
    last_update: Instant,
    last_frame: Instant,
    dt_update_in_ns: u64,
    dt_frame_in_ns: u64,
    dt: f64,
    swap_buffers: bool,
    bench_mode: bool,
}

static BILLION: u64 = 1_000_000_000;

fn ns_to_duration(ns: u64) -> Duration {
    let secs = ns / BILLION;
    let nanos = (ns % BILLION) as u32;
    Duration::new(secs, nanos)
}

fn duration_to_f64(dur: Duration) -> f64 {
    dur.as_secs() as f64 + dur.subsec_nanos() as f64 / 1000_000_000.0
}

/// The default updates per second.
pub const DEFAULT_UPS: u64 = 120;
/// The default maximum frames per second.
pub const DEFAULT_MAX_FPS: u64 = 60;

impl WindowEvents
{
    /// Creates a new event iterator with default UPS and FPS settings.
    pub fn new() -> WindowEvents {
        let start = Instant::now();
        let updates_per_second = DEFAULT_UPS;
        let max_frames_per_second = DEFAULT_MAX_FPS;
        WindowEvents {
            state: State::Render,
            last_update: start,
            last_frame: start,
            dt_update_in_ns: BILLION / updates_per_second,
            dt_frame_in_ns: BILLION / max_frames_per_second,
            dt: 1.0 / updates_per_second as f64,
            swap_buffers: true,
            bench_mode: false,
        }
    }

    /// Returns the next game event.
    pub fn next<W>(&mut self, window: &mut W) -> Option<Event<W::Event>>
        where W: Window
    {
        loop {
            if window.should_close() { return None; }
            self.state = match self.state {
                State::Render => {
                    // Handle input events before rendering,
                    // because window might be closed and destroy
                    // the graphics context.
                    if let Some(e) = window.poll_event() {
                        if self.bench_mode {
                            // Ignore input events in benchmark mode.
                            // This is to avoid the input events affecting
                            // the application state when benchmarking.
                            continue
                        } else {
                            return Some(Event::Input(e));
                        }
                    }
                    if window.should_close() {
                        return None;
                    }

                    if self.bench_mode {
                        // In benchmark mode, pretend FPS is perfect.
                        self.last_frame += ns_to_duration(self.dt_frame_in_ns);
                    } else {
                        // In normal mode, let the FPS slip if late.
                        self.last_frame = Instant::now();
                    }

                    let size = window.size();
                    let draw_size = window.draw_size();
                    if size.width != 0 && size.height != 0 {
                        // Swap buffers next time.
                        self.state = State::SwapBuffers;
                        return Some(Event::Render(RenderArgs {
                            // Extrapolate time forward to allow smooth motion.
                            ext_dt: duration_to_f64(self.last_frame.duration_since(self.last_update))
                                    / BILLION as f64,
                            width: size.width,
                            height: size.height,
                            draw_width: draw_size.width,
                            draw_height: draw_size.height,
                        }));
                    }

                    State::UpdateLoop(Idle::No)
                }
                State::SwapBuffers => {
                    if self.swap_buffers {
                        window.swap_buffers();
                    }
                    self.state = State::UpdateLoop(Idle::No);
                    return Some(Event::AfterRender(AfterRenderArgs));
                }
                State::UpdateLoop(ref mut idle) => {
                    if self.bench_mode {
                        // In benchmark mode, pick the next event without sleep.
                        // Idle and input events are ignored.
                        // This is to avoid the input events affecting
                        // the application state when benchmarking.
                        let next_frame = self.last_frame + ns_to_duration(self.dt_frame_in_ns);
                        let next_update = self.last_update + ns_to_duration(self.dt_update_in_ns);
                        let next_event = cmp::min(next_frame, next_update);
                        if next_event == next_frame {
                            State::Render
                        } else {
                            State::HandleEvents(UpdateState {
                                dt_update_in_ns: self.dt_update_in_ns,
                                dt: self.dt,
                            })
                        }
                    } else {
                        let current_time = Instant::now();
                        let next_frame = self.last_frame + ns_to_duration(self.dt_frame_in_ns);
                        let next_update = self.last_update + ns_to_duration(self.dt_update_in_ns);
                        let next_event = cmp::min(next_frame, next_update);
                        if next_event > current_time {
                            if let Some(x) = window.poll_event() {
                                *idle = Idle::No;
                                return Some(Event::Input(x));
                            } else if *idle == Idle::No {
                                *idle = Idle::Yes;
                                let seconds = duration_to_f64(next_event - current_time) / (BILLION as f64);
                                return Some(Event::Idle(IdleArgs { dt: seconds }))
                            }
                            sleep(next_event - current_time);
                            State::UpdateLoop(Idle::No)
                        } else if next_event == next_frame {
                            State::Render
                        } else {
                            State::HandleEvents(UpdateState {
                                dt_update_in_ns: self.dt_update_in_ns,
                                dt: self.dt,
                            })
                        }
                    }
                }
                State::HandleEvents(update_state) => {
                    if self.bench_mode {
                        // Ignore input events.
                        // This is to avoid the input events affecting
                        // the application state when benchmarking.
                        match window.poll_event() {
                            None => State::Update(update_state),
                            Some(_) => State::HandleEvents(update_state),
                        }
                    } else {
                        // Handle all events before updating.
                        match window.poll_event() {
                            None => State::Update(update_state),
                            Some(x) => { return Some(Event::Input(x)); },
                        }
                    }
                }
                State::Update(update_state) => {
                    self.state = State::UpdateLoop(Idle::No);
                    // Use the update state stored right after sleep.
                    // If there are any changes in settings, these will be applied on next update.
                    self.last_update += ns_to_duration(update_state.dt_update_in_ns);
                    return Some(Event::Update(UpdateArgs{ dt: update_state.dt }));
                }
            };
        }
    }
}

impl EventLoop for WindowEvents {
    fn set_ups(&mut self, frames: u64) {
        self.dt_update_in_ns = BILLION / frames;
        self.dt = 1.0 / frames as f64;
    }

    fn set_max_fps(&mut self, frames: u64) {
        self.dt_frame_in_ns = BILLION / frames;
    }

    fn set_swap_buffers(&mut self, enable: bool) {
        self.swap_buffers = enable;
    }

    fn set_bench_mode(&mut self, enable: bool) {
        self.bench_mode = enable;
    }
}
<commit_msg>corrected units for dt and ext_dt in Event::Idle and Event::Render back to seconds<commit_after>//! A generic event loop for games and interactive applications

#![deny(missing_docs)]
#![deny(missing_copy_implementations)]

extern crate window;
extern crate input;
extern crate viewport;

use std::thread::sleep;
use std::time::{Duration, Instant};
use std::cmp;
use window::Window;
use input::{ AfterRenderArgs, Event, IdleArgs, RenderArgs, UpdateArgs };

/// A trait for create event iterator from window.
pub trait Events {
    /// Creates event iterator from window.
    fn events(&self) -> WindowEvents;
}

impl<W> Events for W where W: Window {
    fn events(&self) -> WindowEvents {
        WindowEvents::new()
    }
}

/// Tells whether last emitted event was idle or not.
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
enum Idle {
    No,
    Yes
}

// Stores the update state right after sleep.
// This is used to avoid logic error when changing settings
// in the event loop followed by an update.
#[derive(Copy, Clone, Debug)]
struct UpdateState {
    dt_update_in_ns: u64,
    dt: f64,
}

#[derive(Copy, Clone, Debug)]
enum State {
    Render,
    SwapBuffers,
    UpdateLoop(Idle),
    HandleEvents(UpdateState),
    Update(UpdateState),
}

/// Methods implements for event loop settings.
pub trait EventLoop: Sized {
    /// The number of updates per second
    ///
    /// This is the fixed update rate on average over time.
    /// If the event loop lags, it will try to catch up.
    fn set_ups(&mut self, frames: u64);

    /// The number of updates per second
    ///
    /// This is the fixed update rate on average over time.
    /// If the event loop lags, it will try to catch up.
    fn ups(mut self, frames: u64) -> Self {
        self.set_ups(frames);
        self
    }

    /// The maximum number of frames per second
    ///
    /// The frame rate can be lower because the
    /// next frame is always scheduled from the previous frame.
    /// This causes the frames to "slip" over time.
    fn set_max_fps(&mut self, frames: u64);

    /// The maximum number of frames per second
    ///
    /// The frame rate can be lower because the
    /// next frame is always scheduled from the previous frame.
    /// This causes the frames to "slip" over time.
    fn max_fps(mut self, frames: u64) -> Self {
        self.set_max_fps(frames);
        self
    }

    /// Enable or disable automatic swapping of buffers.
    fn set_swap_buffers(&mut self, enable: bool);

    /// Enable or disable automatic swapping of buffers.
    fn swap_buffers(mut self, enable: bool) -> Self {
        self.set_swap_buffers(enable);
        self
    }

    /// Enable or disable benchmark mode.
    /// When enabled, it will render and update without sleep and ignore input.
    /// Used to test performance by playing through as fast as possible.
    fn set_bench_mode(&mut self, enable: bool);

    /// Enable or disable benchmark mode.
    /// When enabled, it will render and update without sleep and ignore input.
    /// Used to test performance by playing through as fast as possible.
    fn bench_mode(mut self, enable: bool) -> Self {
        self.set_bench_mode(enable);
        self
    }
}

/// An event loop iterator
///
/// *Warning: Because the iterator polls events from the window back-end,
/// it must be used on the same thread as the window back-end (usually main thread),
/// unless the window back-end supports multi-thread event polling.*
#[derive(Copy, Clone)]
pub struct WindowEvents {
    state: State,
    last_update: Instant,
    last_frame: Instant,
    dt_update_in_ns: u64,
    dt_frame_in_ns: u64,
    dt: f64,
    swap_buffers: bool,
    bench_mode: bool,
}

static BILLION: u64 = 1_000_000_000;

fn ns_to_duration(ns: u64) -> Duration {
    let secs = ns / BILLION;
    let nanos = (ns % BILLION) as u32;
    Duration::new(secs, nanos)
}

fn duration_to_secs(dur: Duration) -> f64 {
    dur.as_secs() as f64 + dur.subsec_nanos() as f64 / 1000_000_000.0
}

/// The default updates per second.
pub const DEFAULT_UPS: u64 = 120;
/// The default maximum frames per second.
pub const DEFAULT_MAX_FPS: u64 = 60;

impl WindowEvents
{
    /// Creates a new event iterator with default UPS and FPS settings.
    pub fn new() -> WindowEvents {
        let start = Instant::now();
        let updates_per_second = DEFAULT_UPS;
        let max_frames_per_second = DEFAULT_MAX_FPS;
        WindowEvents {
            state: State::Render,
            last_update: start,
            last_frame: start,
            dt_update_in_ns: BILLION / updates_per_second,
            dt_frame_in_ns: BILLION / max_frames_per_second,
            dt: 1.0 / updates_per_second as f64,
            swap_buffers: true,
            bench_mode: false,
        }
    }

    /// Returns the next game event.
    pub fn next<W>(&mut self, window: &mut W) -> Option<Event<W::Event>>
        where W: Window
    {
        loop {
            if window.should_close() { return None; }
            self.state = match self.state {
                State::Render => {
                    // Handle input events before rendering,
                    // because window might be closed and destroy
                    // the graphics context.
                    if let Some(e) = window.poll_event() {
                        if self.bench_mode {
                            // Ignore input events in benchmark mode.
                            // This is to avoid the input events affecting
                            // the application state when benchmarking.
                            continue
                        } else {
                            return Some(Event::Input(e));
                        }
                    }
                    if window.should_close() {
                        return None;
                    }

                    if self.bench_mode {
                        // In benchmark mode, pretend FPS is perfect.
                        self.last_frame += ns_to_duration(self.dt_frame_in_ns);
                    } else {
                        // In normal mode, let the FPS slip if late.
                        self.last_frame = Instant::now();
                    }

                    let size = window.size();
                    let draw_size = window.draw_size();
                    if size.width != 0 && size.height != 0 {
                        // Swap buffers next time.
                        self.state = State::SwapBuffers;
                        return Some(Event::Render(RenderArgs {
                            // Extrapolate time forward to allow smooth motion.
                            ext_dt: duration_to_secs(self.last_frame.duration_since(self.last_update)),
                            width: size.width,
                            height: size.height,
                            draw_width: draw_size.width,
                            draw_height: draw_size.height,
                        }));
                    }

                    State::UpdateLoop(Idle::No)
                }
                State::SwapBuffers => {
                    if self.swap_buffers {
                        window.swap_buffers();
                    }
                    self.state = State::UpdateLoop(Idle::No);
                    return Some(Event::AfterRender(AfterRenderArgs));
                }
                State::UpdateLoop(ref mut idle) => {
                    if self.bench_mode {
                        // In benchmark mode, pick the next event without sleep.
                        // Idle and input events are ignored.
                        // This is to avoid the input events affecting
                        // the application state when benchmarking.
                        let next_frame = self.last_frame + ns_to_duration(self.dt_frame_in_ns);
                        let next_update = self.last_update + ns_to_duration(self.dt_update_in_ns);
                        let next_event = cmp::min(next_frame, next_update);
                        if next_event == next_frame {
                            State::Render
                        } else {
                            State::HandleEvents(UpdateState {
                                dt_update_in_ns: self.dt_update_in_ns,
                                dt: self.dt,
                            })
                        }
                    } else {
                        let current_time = Instant::now();
                        let next_frame = self.last_frame + ns_to_duration(self.dt_frame_in_ns);
                        let next_update = self.last_update + ns_to_duration(self.dt_update_in_ns);
                        let next_event = cmp::min(next_frame, next_update);
                        if next_event > current_time {
                            if let Some(x) = window.poll_event() {
                                *idle = Idle::No;
                                return Some(Event::Input(x));
                            } else if *idle == Idle::No {
                                *idle = Idle::Yes;
                                let seconds = duration_to_secs(next_event - current_time);
                                return Some(Event::Idle(IdleArgs { dt: seconds }))
                            }
                            sleep(next_event - current_time);
                            State::UpdateLoop(Idle::No)
                        } else if next_event == next_frame {
                            State::Render
                        } else {
                            State::HandleEvents(UpdateState {
                                dt_update_in_ns: self.dt_update_in_ns,
                                dt: self.dt,
                            })
                        }
                    }
                }
                State::HandleEvents(update_state) => {
                    if self.bench_mode {
                        // Ignore input events.
                        // This is to avoid the input events affecting
                        // the application state when benchmarking.
                        match window.poll_event() {
                            None => State::Update(update_state),
                            Some(_) => State::HandleEvents(update_state),
                        }
                    } else {
                        // Handle all events before updating.
                        match window.poll_event() {
                            None => State::Update(update_state),
                            Some(x) => { return Some(Event::Input(x)); },
                        }
                    }
                }
                State::Update(update_state) => {
                    self.state = State::UpdateLoop(Idle::No);
                    // Use the update state stored right after sleep.
                    // If there are any changes in settings, these will be applied on next update.
                    self.last_update += ns_to_duration(update_state.dt_update_in_ns);
                    return Some(Event::Update(UpdateArgs{ dt: update_state.dt }));
                }
            };
        }
    }
}

impl EventLoop for WindowEvents {
    fn set_ups(&mut self, frames: u64) {
        self.dt_update_in_ns = BILLION / frames;
        self.dt = 1.0 / frames as f64;
    }

    fn set_max_fps(&mut self, frames: u64) {
        self.dt_frame_in_ns = BILLION / frames;
    }

    fn set_swap_buffers(&mut self, enable: bool) {
        self.swap_buffers = enable;
    }

    fn set_bench_mode(&mut self, enable: bool) {
        self.bench_mode = enable;
    }
}
<|endoftext|>


<commit_before>use super::TestValidator;
pub use beacon_chain::dump::{Error as DumpError, SlotDump};
use beacon_chain::BeaconChain;
use db::{
    stores::{BeaconBlockStore, BeaconStateStore},
    MemoryDB,
};
use log::debug;
use rayon::prelude::*;
use slot_clock::TestingSlotClock;
use std::fs::File;
use std::io::prelude::*;
use std::sync::Arc;
use types::{BeaconBlock, ChainSpec, FreeAttestation, Keypair, Validator};

pub struct BeaconChainHarness {
    pub db: Arc<MemoryDB>,
    pub beacon_chain: Arc<BeaconChain<MemoryDB, TestingSlotClock>>,
    pub block_store: Arc<BeaconBlockStore<MemoryDB>>,
    pub state_store: Arc<BeaconStateStore<MemoryDB>>,
    pub validators: Vec<TestValidator>,
    pub spec: ChainSpec,
}

impl BeaconChainHarness {
    pub fn new(mut spec: ChainSpec, validator_count: usize) -> Self {
        let db = Arc::new(MemoryDB::open());
        let block_store = Arc::new(BeaconBlockStore::new(db.clone()));
        let state_store = Arc::new(BeaconStateStore::new(db.clone()));

        let slot_clock = TestingSlotClock::new(spec.genesis_slot);

        // Remove the validators present in the spec (if any).
        spec.initial_validators = Vec::with_capacity(validator_count);
        spec.initial_balances = Vec::with_capacity(validator_count);

        debug!("Generating validator keypairs...");

        let keypairs: Vec<Keypair> = (0..validator_count)
            .collect::<Vec<usize>>()
            .par_iter()
            .map(|_| Keypair::random())
            .collect();

        debug!("Creating validator records...");

        spec.initial_validators = keypairs
            .par_iter()
            .map(|keypair| Validator {
                pubkey: keypair.pk.clone(),
                activation_slot: 0,
                ..std::default::Default::default()
            })
            .collect();

        debug!("Setting validator balances...");

        spec.initial_balances = spec
            .initial_validators
            .par_iter()
            .map(|_| 32_000_000_000) // 32 ETH
            .collect();

        debug!("Creating the BeaconChain...");

        // Create the Beacon Chain
        let beacon_chain = Arc::new(
            BeaconChain::genesis(
                state_store.clone(),
                block_store.clone(),
                slot_clock,
                spec.clone(),
            )
            .unwrap(),
        );

        debug!("Creating validator producer and attester instances...");

        // Spawn the test validator instances.
        let validators: Vec<TestValidator> = keypairs
            .par_iter()
            .map(|keypair| TestValidator::new(keypair.clone(), beacon_chain.clone(), &spec))
            .collect();

        debug!("Created {} TestValidators", validators.len());

        Self {
            db,
            beacon_chain,
            block_store,
            state_store,
            validators,
            spec,
        }
    }

    /// Move the `slot_clock` for the `BeaconChain` forward one slot.
    ///
    /// This is the equivalent of advancing a system clock forward one `SLOT_DURATION`.
    pub fn increment_beacon_chain_slot(&mut self) {
        let slot = self
            .beacon_chain
            .present_slot()
            .expect("Unable to determine slot.")
            + 1;

        debug!("Incrementing BeaconChain slot to {}.", slot);

        self.beacon_chain.slot_clock.set_slot(slot);
    }

    /// Gather the `FreeAttestation`s from the valiators.
    ///
    /// Note: validators will only produce attestations _once per slot_. So, if you call this twice
    /// you'll only get attestations on the first run.
    pub fn gather_free_attesations(&mut self) -> Vec<FreeAttestation> {
        let present_slot = self.beacon_chain.present_slot().unwrap();

        let free_attestations: Vec<FreeAttestation> = self
            .validators
            .par_iter_mut()
            .filter_map(|validator| {
                // Advance the validator slot.
                validator.set_slot(present_slot);

                // Prompt the validator to produce an attestation (if required).
                validator.produce_free_attestation().ok()
            })
            .collect();

        debug!(
            "Gathered {} FreeAttestations for slot {}.",
            free_attestations.len(),
            present_slot
        );

        free_attestations
    }

    /// Get the block from the proposer for the slot.
    ///
    /// Note: the validator will only produce it _once per slot_. So, if you call this twice you'll
    /// only get a block once.
    pub fn produce_block(&mut self) -> BeaconBlock {
        let present_slot = self.beacon_chain.present_slot().unwrap();

        let proposer = self.beacon_chain.block_proposer(present_slot).unwrap();

        debug!(
            "Producing block from validator #{} for slot {}.",
            proposer, present_slot
        );

        self.validators[proposer].produce_block().unwrap()
    }

    /// Advances the chain with a BeaconBlock and attestations from all validators.
    ///
    /// This is the ideal scenario for the Beacon Chain, 100% honest participation from
    /// validators.
    pub fn advance_chain_with_block(&mut self) {
        self.increment_beacon_chain_slot();
        let free_attestations = self.gather_free_attesations();
        for free_attestation in free_attestations {
            self.beacon_chain
                .process_free_attestation(free_attestation.clone())
                .unwrap();
        }
        let block = self.produce_block();
        debug!("Submitting block for processing...");
        self.beacon_chain.process_block(block).unwrap();
        debug!("...block processed by BeaconChain.");
    }

    pub fn chain_dump(&self) -> Result<Vec<SlotDump>, DumpError> {
        self.beacon_chain.chain_dump()
    }

    pub fn dump_to_file(&self, filename: String, chain_dump: &Vec<SlotDump>) {
        let json = serde_json::to_string(chain_dump).unwrap();
        let mut file = File::create(filename).unwrap();
        file.write_all(json.as_bytes())
            .expect("Failed writing dump to file.");
    }
}
<commit_msg>Ensure harness produces block before attestations.<commit_after>use super::TestValidator;
pub use beacon_chain::dump::{Error as DumpError, SlotDump};
use beacon_chain::BeaconChain;
use db::{
    stores::{BeaconBlockStore, BeaconStateStore},
    MemoryDB,
};
use log::debug;
use rayon::prelude::*;
use slot_clock::TestingSlotClock;
use std::fs::File;
use std::io::prelude::*;
use std::sync::Arc;
use types::{BeaconBlock, ChainSpec, FreeAttestation, Keypair, Validator};

pub struct BeaconChainHarness {
    pub db: Arc<MemoryDB>,
    pub beacon_chain: Arc<BeaconChain<MemoryDB, TestingSlotClock>>,
    pub block_store: Arc<BeaconBlockStore<MemoryDB>>,
    pub state_store: Arc<BeaconStateStore<MemoryDB>>,
    pub validators: Vec<TestValidator>,
    pub spec: ChainSpec,
}

impl BeaconChainHarness {
    pub fn new(mut spec: ChainSpec, validator_count: usize) -> Self {
        let db = Arc::new(MemoryDB::open());
        let block_store = Arc::new(BeaconBlockStore::new(db.clone()));
        let state_store = Arc::new(BeaconStateStore::new(db.clone()));

        let slot_clock = TestingSlotClock::new(spec.genesis_slot);

        // Remove the validators present in the spec (if any).
        spec.initial_validators = Vec::with_capacity(validator_count);
        spec.initial_balances = Vec::with_capacity(validator_count);

        debug!("Generating validator keypairs...");

        let keypairs: Vec<Keypair> = (0..validator_count)
            .collect::<Vec<usize>>()
            .par_iter()
            .map(|_| Keypair::random())
            .collect();

        debug!("Creating validator records...");

        spec.initial_validators = keypairs
            .par_iter()
            .map(|keypair| Validator {
                pubkey: keypair.pk.clone(),
                activation_slot: 0,
                ..std::default::Default::default()
            })
            .collect();

        debug!("Setting validator balances...");

        spec.initial_balances = spec
            .initial_validators
            .par_iter()
            .map(|_| 32_000_000_000) // 32 ETH
            .collect();

        debug!("Creating the BeaconChain...");

        // Create the Beacon Chain
        let beacon_chain = Arc::new(
            BeaconChain::genesis(
                state_store.clone(),
                block_store.clone(),
                slot_clock,
                spec.clone(),
            )
            .unwrap(),
        );

        debug!("Creating validator producer and attester instances...");

        // Spawn the test validator instances.
        let validators: Vec<TestValidator> = keypairs
            .par_iter()
            .map(|keypair| TestValidator::new(keypair.clone(), beacon_chain.clone(), &spec))
            .collect();

        debug!("Created {} TestValidators", validators.len());

        Self {
            db,
            beacon_chain,
            block_store,
            state_store,
            validators,
            spec,
        }
    }

    /// Move the `slot_clock` for the `BeaconChain` forward one slot.
    ///
    /// This is the equivalent of advancing a system clock forward one `SLOT_DURATION`.
    ///
    /// Returns the new slot.
    pub fn increment_beacon_chain_slot(&mut self) -> u64 {
        let slot = self
            .beacon_chain
            .present_slot()
            .expect("Unable to determine slot.")
            + 1;

        debug!("Incrementing BeaconChain slot to {}.", slot);

        self.beacon_chain.slot_clock.set_slot(slot);
        slot
    }

    /// Gather the `FreeAttestation`s from the valiators.
    ///
    /// Note: validators will only produce attestations _once per slot_. So, if you call this twice
    /// you'll only get attestations on the first run.
    pub fn gather_free_attesations(&mut self) -> Vec<FreeAttestation> {
        let present_slot = self.beacon_chain.present_slot().unwrap();

        let free_attestations: Vec<FreeAttestation> = self
            .validators
            .par_iter_mut()
            .filter_map(|validator| {
                // Advance the validator slot.
                validator.set_slot(present_slot);

                // Prompt the validator to produce an attestation (if required).
                validator.produce_free_attestation().ok()
            })
            .collect();

        debug!(
            "Gathered {} FreeAttestations for slot {}.",
            free_attestations.len(),
            present_slot
        );

        free_attestations
    }

    /// Get the block from the proposer for the slot.
    ///
    /// Note: the validator will only produce it _once per slot_. So, if you call this twice you'll
    /// only get a block once.
    pub fn produce_block(&mut self) -> BeaconBlock {
        let present_slot = self.beacon_chain.present_slot().unwrap();

        let proposer = self.beacon_chain.block_proposer(present_slot).unwrap();

        debug!(
            "Producing block from validator #{} for slot {}.",
            proposer, present_slot
        );

        // Ensure the validators slot clock is accurate.
        self.validators[proposer].set_slot(present_slot);
        self.validators[proposer].produce_block().unwrap()
    }

    /// Advances the chain with a BeaconBlock and attestations from all validators.
    ///
    /// This is the ideal scenario for the Beacon Chain, 100% honest participation from
    /// validators.
    pub fn advance_chain_with_block(&mut self) {
        self.increment_beacon_chain_slot();

        // Produce a new block.
        let block = self.produce_block();
        debug!("Submitting block for processing...");
        self.beacon_chain.process_block(block).unwrap();
        debug!("...block processed by BeaconChain.");

        // Produce new attestations.
        let free_attestations = self.gather_free_attesations();
        for free_attestation in free_attestations {
            self.beacon_chain
                .process_free_attestation(free_attestation)
                .unwrap();
        }
    }

    pub fn chain_dump(&self) -> Result<Vec<SlotDump>, DumpError> {
        self.beacon_chain.chain_dump()
    }

    pub fn dump_to_file(&self, filename: String, chain_dump: &Vec<SlotDump>) {
        let json = serde_json::to_string(chain_dump).unwrap();
        let mut file = File::create(filename).unwrap();
        file.write_all(json.as_bytes())
            .expect("Failed writing dump to file.");
    }
}
<|endoftext|>