<commit_before>//! Event API for the lua thread

// TODO look up Awesome API stuff
pub enum Event {
    Timer(String),
    /// Named channels that can send arbitrary data
    Message(String, AnyLuaValue),
    ViewCreated,
    ViewFocus,
}
<commit_msg>Removed event.rs<commit_after><|endoftext|>


<commit_before>// Kevin Cantu
// Boyer-Moore string searching

use std;

// Function: findn_bytes
//
// Boyer-Moore string search, which returns
// up to `nn` byte positions of matched substrings
fn findn_bytes (needle: str, haystack: str, nn: uint) -> [uint] {
   let results = [];
   let ct = char_table(needle);
   let pt = prefix_table(needle);

   log(error, ct);
   log(error, pt);

   let ii = 0u;
   let jj = 0u;

   while ii < str::len_bytes(haystack) {

      jj = str::len_bytes(needle);

      // reverse through needle
      while 0u <= jj {
         jj -= 1u;

         // if still matching
         if needle[jj] == haystack[ii] {
            // if full match
            if jj == 0u {
               vec::push(results, jj);
               if vec::len(results) >= nn { ret results; }
            }

         // if partial match
         } else {
            let sufn = str::len_bytes(needle) - jj;

            let ctx;
            let ptx;

            alt ct.find(needle[sufn] as uint) {
               option::none { ctx = str::len_bytes(needle);}
               option::some(x) { ctx = x;}
            }

            alt pt.find(sufn) {
               option::none { fail "something is out of range" }
               option::some(x) { ptx = x;}
            }

            ii += greaterOf(ctx, ptx) - jj;
            jj = 0u;
         }
      }

      ii += 1u;
   }

   ret results;
}

fn char_table (needle: str) -> std::map::map<uint, uint> {
   let mm: std::map::map<uint, uint> = std::map::new_uint_hash();
   let len = str::len_bytes(needle);

   let jj = len - 1u; // drop the last byte

   // from last-1 to first
   while jj > 0u {
      jj -= 1u;
      if ! mm.contains_key(needle[jj] as uint) {
         // store reverse indexes
         mm.insert(needle[jj] as uint, len - 1u - jj);
      }
   }

   ret mm;
}

#[test]
fn test_char_table () {
   let ct = char_table("ANPANMAN");
   assert 1u == ct.get('A' as uint);
   assert 2u == ct.get('M' as uint);
   assert 3u == ct.get('N' as uint);
   assert 5u == ct.get('P' as uint);
   assert option::none == ct.find('z' as uint);
}

fn prefix_table (needle: str) -> std::map::map<uint, uint> {
   let mm: std::map::map<uint, uint> = std::map::new_uint_hash();

   let prefs = vec::reversed(prefixes(needle)); // largest first
   let sufs  = vec::reversed(suffixes(needle)); // smallest first
   let jj    = 0u;
   let kk    = 0u;
   let lim   = str::len(needle);

   while jj < lim {    // sufixes
      std::io::println("\n<newsuff: " + sufs[jj] + ">");

      kk = 0u;

      while kk < lim { // prefixes
         std::io::print("<prefixes: " + prefs[kk] + "> ");

         let suf = sufs[jj];
         let pref = prefs[kk];

         // combine this logic

         if str::len_bytes(pref) > str::len_bytes(suf) {
            //std::io::println("[" + pref + ", " + suf + "]");
            std::io::print("(pref > suf)");
            if str::ends_with(pref, suf) {
               std::io::print("(ew)");
               if !str::ends_with(pref, sufs[jj+1u]) {
                  std::io::print("(ew+1)");

                  if ! mm.contains_key(jj)
                  {
                     std::io::print(#fmt("(+%u)", kk));
                     mm.insert(jj, kk);
                  }
               }
            }
         }

         if str::len_bytes(pref) <= str::len_bytes(suf) {
            std::io::print("(pref <= suf)");

            if str::ends_with(suf, pref) // partial
            {
               std::io::print("(^ew)");

               if ! mm.contains_key(jj)
               {
                  std::io::print(#fmt("(*%u)", kk));
                  mm.insert(jj, kk);
               }
            }
         }

         std::io::println("");

         kk += 1u;
      }

      // for this suffix jj, if no matching prefix, where did we fall out?
      // i.e., what is the last prefix that was still partially matching,
      // e.g., for suffix "man", the prefix "an" works, and is +6...

      if ! mm.contains_key(jj)
      {
         std::io::print(#fmt("(=%u)", kk));
         mm.insert(jj, kk);
      }

      jj += 1u;
   }

   ret mm
}

#[test]
fn test_prefix_table() {
   let pt = prefix_table("ANPANMAN");
                        //     ... 8
   std::io::print("+");
   log(error, pt);
   assert 1u == pt.get(0u); //        (n)
   assert 8u == pt.get(1u); //       (a)n
   assert 3u == pt.get(2u); //      (m)an
   assert 6u == pt.get(3u); //     (n)man
   assert 6u == pt.get(4u); //    (a)nman
   assert 6u == pt.get(5u); //   (p)anman
   assert 6u == pt.get(6u); //  (n)panman
   assert 6u == pt.get(7u); // (a)npanman
   //assert 0u == pt.get(8u); // fail
}

////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////

// prefixes, smallest first
fn prefixes(ss: str) -> [str] unsafe {
   let vv = [];
   let sz = 0u;
   vec::push(vv, "");
   str::bytes_iter(ss) {|_bb|
      sz += 1u;
      vec::push(vv, str::unsafe::slice_bytes(ss, 0u, sz));
   }
   ret vv;
}

#[test]
fn test_prefs() {
   assert ["", "a", "ab", "abc", "abcd"] == prefixes("abcd");
}

// suffixes, largest first
fn suffixes(ss: str) -> [str] unsafe {
   let vv = [];
   let sz = 0u;
   let lim = str::len_bytes(ss);
   str::bytes_iter(ss) {|_bb|
      vec::push(vv, str::unsafe::slice_bytes(ss, sz, lim));
      sz += 1u;
   }
   vec::push(vv, "");
   ret vv;
}

#[test]
fn test_sufs() {
   assert ["abcd", "bcd", "cd", "d", ""] == suffixes("abcd");
}

fn greaterOf(a: uint, b: uint) -> uint {
   if a > b { ret a; } else { ret b; }
}

#[test]
fn test_greaterOf() {
   assert greaterOf(15u, 17u) == 17u;
   assert greaterOf(17u, 15u) == 17u;
}

fn find_bytes_(needle: str, haystack: str) -> option<uint> {
   ret option::some(findn_bytes(needle, haystack, 1u)[0u]);
}

#[test]
fn test_find_bytes() {
  // byte positions
  assert (find_bytes_("banana", "apple pie") == option::none);
  assert (find_bytes_("", "") == option::some(0u));

  let data = "ประเทศไทย中华Việt Nam";
  assert (find_bytes_(data, "")     == option::some(0u));
  assert (find_bytes_(data, "ประเ") == option::some( 0u));
  assert (find_bytes_(data, "ะเ")   == option::some( 6u));
  assert (find_bytes_(data, "中华") == option::some(27u));
  assert (find_bytes_(data, "ไท华") == option::none);
}

<commit_msg>(boyer-moore) finding still broken...<commit_after>// Kevin Cantu
// Boyer-Moore string searching

use std;

// Function: findn_bytes
//
// Boyer-Moore string search, which returns
// up to `nn` byte positions of matched substrings
fn findn_bytes (needle: str, haystack: str, nn: uint) -> [uint] {
   let results = [];
   let ct = char_table(needle);
   let pt = prefix_table(needle);

   //log(error, ct);
   //log(error, pt);

   let ii = 0u;
   let jj = 0u;

   while ii < str::len_bytes(haystack) {
      std::io::print(".");

      jj = str::len_bytes(needle);

      // reverse through needle
      while 0u < jj {
         std::io::print("+");

         jj -= 1u;

         // if still matching
         if needle[jj] == haystack[ii] {
            std::io::print("(= " + #fmt("%u", jj) + ")");

            // if full match
            if jj == 0u {
               vec::push(results, jj);
               if vec::len(results) >= nn { ret results; }
            }

         // if partial match
         } else {
            std::io::print("(| " + #fmt("%u", jj) + ")");

            let sufn = str::len_bytes(needle) - jj;

            let ctx;
            let ptx;

            alt ct.find(needle[sufn] as uint) {
               option::none { ctx = str::len_bytes(needle);}
               option::some(x) { ctx = x;}
            }

            alt pt.find(sufn) {
               option::none { fail "something is out of range" }
               option::some(x) { ptx = x;}
            }

            ii += greaterOf(ctx, ptx) + sufn;

            jj = 0u;
         }
      }

      std::io::println("");
      ii += 1u;
   }

   ret results;
}

fn char_table (needle: str) -> std::map::map<uint, uint> {
   let mm: std::map::map<uint, uint> = std::map::new_uint_hash();
   let len = str::len_bytes(needle);

   let jj = len - 1u; // drop the last byte

   // from last-1 to first
   while jj > 0u {
      jj -= 1u;
      if ! mm.contains_key(needle[jj] as uint) {
         // store reverse indexes
         mm.insert(needle[jj] as uint, len - 1u - jj);
      }
   }

   ret mm;
}

#[test]
fn test_char_table () {
   let ct = char_table("ANPANMAN");
   assert 1u == ct.get('A' as uint);
   assert 2u == ct.get('M' as uint);
   assert 3u == ct.get('N' as uint);
   assert 5u == ct.get('P' as uint);
   assert option::none == ct.find('z' as uint);
}

fn prefix_table (needle: str) -> std::map::map<uint, uint> {
   let mm: std::map::map<uint, uint> = std::map::new_uint_hash();

   let prefs = vec::reversed(prefixes(needle)); // largest first
   let sufs  = vec::reversed(suffixes(needle)); // smallest first
   let jj    = 0u;
   let kk    = 0u;
   let lim   = str::len(needle);

   while jj < lim {    // sufixes
//      std::io::println("\n<newsuff: " + sufs[jj] + ">");

      kk = 0u;

      while kk < lim { // prefixes
//         std::io::print("<prefixes: " + prefs[kk] + "> ");

         let suf = sufs[jj];
         let pref = prefs[kk];

         // combine this logic

         if str::len_bytes(pref) > str::len_bytes(suf) {
//            std::io::print("(pref > suf)");
            if str::ends_with(pref, suf) {
//               std::io::print("(ew)");
               if !str::ends_with(pref, sufs[jj+1u]) {
//                  std::io::print("(ew+1)");

                  if ! mm.contains_key(jj)
                  {
//                     std::io::print(#fmt("(+%u)", kk));
                     mm.insert(jj, kk);
                  }
               }
            }
         }

         if str::len_bytes(pref) <= str::len_bytes(suf) {
//            std::io::print("(pref <= suf)");

            if str::ends_with(suf, pref) // partial
            {
//               std::io::print("(^ew)");

               if ! mm.contains_key(jj)
               {
//                  std::io::print(#fmt("(*%u)", kk));
                  mm.insert(jj, kk);
               }
            }
         }

//         std::io::println("");

         kk += 1u;
      }

      // for this suffix jj, if no matching prefix, where did we fall out?
      // i.e., what is the last prefix that was still partially matching,
      // e.g., for suffix "man", the prefix "an" works, and is +6...

      if ! mm.contains_key(jj)
      {
//         std::io::print(#fmt("(=%u)", kk));
         mm.insert(jj, kk);
      }

      jj += 1u;
   }

   ret mm
}

#[test]
fn test_prefix_table() {
   let pt = prefix_table("ANPANMAN");
                        //     ... 8
//   std::io::print("+");

   assert 1u == pt.get(0u); //        (n)
   assert 8u == pt.get(1u); //       (a)n
   assert 3u == pt.get(2u); //      (m)an
   assert 6u == pt.get(3u); //     (n)man
   assert 6u == pt.get(4u); //    (a)nman
   assert 6u == pt.get(5u); //   (p)anman
   assert 6u == pt.get(6u); //  (n)panman
   assert 6u == pt.get(7u); // (a)npanman
   //assert 0u == pt.get(8u); // fail
}

////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////

// prefixes, smallest first
fn prefixes(ss: str) -> [str] unsafe {
   let vv = [];
   let sz = 0u;
   vec::push(vv, "");
   str::bytes_iter(ss) {|_bb|
      sz += 1u;
      vec::push(vv, str::unsafe::slice_bytes(ss, 0u, sz));
   }
   ret vv;
}

#[test]
fn test_prefs() {
   assert ["", "a", "ab", "abc", "abcd"] == prefixes("abcd");
}

// suffixes, largest first
fn suffixes(ss: str) -> [str] unsafe {
   let vv = [];
   let sz = 0u;
   let lim = str::len_bytes(ss);
   str::bytes_iter(ss) {|_bb|
      vec::push(vv, str::unsafe::slice_bytes(ss, sz, lim));
      sz += 1u;
   }
   vec::push(vv, "");
   ret vv;
}

#[test]
fn test_sufs() {
   assert ["abcd", "bcd", "cd", "d", ""] == suffixes("abcd");
}

fn greaterOf(a: uint, b: uint) -> uint {
   if a > b { ret a; } else { ret b; }
}

#[test]
fn test_greaterOf() {
   assert greaterOf(15u, 17u) == 17u;
   assert greaterOf(17u, 15u) == 17u;
}

fn find_bytes_(needle: str, haystack: str) -> option<uint> {
   ret option::some(findn_bytes(needle, haystack, 1u)[0u]);
}

#[test]
fn test_find_bytes() {
  // byte positions
  assert (find_bytes_("banana", "apple pie") == option::none);
  assert (find_bytes_("", "") == option::some(0u));

  let data = "ประเทศไทย中华Việt Nam";
  assert (find_bytes_(data, "")     == option::some(0u));
  assert (find_bytes_(data, "ประเ") == option::some( 0u));
  assert (find_bytes_(data, "ะเ")   == option::some( 6u));
  assert (find_bytes_(data, "中华") == option::some(27u));
  assert (find_bytes_(data, "ไท华") == option::none);
}

<|endoftext|>


<commit_before>// Copyright 2012-2014 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

use ast::Name;
use std::cmp;
use parse::token::InternedString;

/// To find the Levenshtein distance between two strings
pub fn lev_distance(a: &str, b: &str) -> usize {
    // cases which don't require further computation
    if a.is_empty() {
        return b.chars().count();
    } else if b.is_empty() {
        return a.chars().count();
    }

    let mut dcol: Vec<_> = (0..b.len() + 1).collect();
    let mut t_last = 0;

    for (i, sc) in a.chars().enumerate() {
        let mut current = i;
        dcol[0] = current + 1;

        for (j, tc) in b.chars().enumerate() {
            let next = dcol[j + 1];
            if sc == tc {
                dcol[j + 1] = current;
            } else {
                dcol[j + 1] = cmp::min(current, next);
                dcol[j + 1] = cmp::min(dcol[j + 1], dcol[j]) + 1;
            }
            current = next;
            t_last = j;
        }
    } dcol[t_last + 1]
}

/// To find the best match for a given string from an iterator of names
/// As a loose rule to avoid the obviously incorrect suggestions, it takes
/// an optional limit for the maximum allowable edit distance, which defaults
/// to one-third of the given word
pub fn find_best_match_for_name<'a, T>(iter_names: T,
                                       lookup: &str,
                                       dist: Option<usize>) -> Option<InternedString>
    where T: Iterator<Item = &'a Name> {
    let max_dist = dist.map_or_else(|| cmp::max(lookup.len(), 3) / 3, |d| d);
    let it = iter_names
    .filter_map(|name| {
        let dist = lev_distance(lookup, &name.as_str());
        match dist <= max_dist {    // filter the unwanted cases
            true => Some((name.as_str(), dist)),
            false => None,
        }
    });
    min_by_key(it, |&(_, val)| val) // extract the tuple containing the minimum edit distance
    .map(|(s, _)| s)                // and return only the string
}

fn min_by_key<I, B: Ord, F>(it: I, f: F) -> Option<I::Item>
    where I: Iterator,
          F: FnMut(&I::Item) -> B,
{
    select_fold1(it,
                 f,
                 // only switch to y if it is strictly smaller, to
                 // preserve stability.
                 |x_p, _, y_p, _| x_p > y_p)
        .map(|(_, x)| x)
}

/// Select an element from an iterator based on the given projection
/// and "comparison" function.
///
/// This is an idiosyncratic helper to try to factor out the
/// commonalities of {max,min}{,_by}. In particular, this avoids
/// having to implement optimizations several times.
#[inline]
fn select_fold1<I,B, FProj, FCmp>(mut it: I,
                                  mut f_proj: FProj,
                                  mut f_cmp: FCmp) -> Option<(B, I::Item)>
    where I: Iterator,
          FProj: FnMut(&I::Item) -> B,
          FCmp: FnMut(&B, &I::Item, &B, &I::Item) -> bool
{
    // start with the first element as our selection. This avoids
    // having to use `Option`s inside the loop, translating to a
    // sizeable performance gain (6x in one case).
    it.next().map(|mut sel| {
        let mut sel_p = f_proj(&sel);

        for x in it {
            let x_p = f_proj(&x);
            if f_cmp(&sel_p,  &sel, &x_p, &x) {
                sel = x;
                sel_p = x_p;
            }
        }
        (sel_p, sel)
    })
}

#[test]
fn test_lev_distance() {
    use std::char::{from_u32, MAX};
    // Test bytelength agnosticity
    for c in (0..MAX as u32)
             .filter_map(|i| from_u32(i))
             .map(|i| i.to_string()) {
        assert_eq!(lev_distance(&c[..], &c[..]), 0);
    }

    let a = "\nMäry häd ä little lämb\n\nLittle lämb\n";
    let b = "\nMary häd ä little lämb\n\nLittle lämb\n";
    let c = "Mary häd ä little lämb\n\nLittle lämb\n";
    assert_eq!(lev_distance(a, b), 1);
    assert_eq!(lev_distance(b, a), 1);
    assert_eq!(lev_distance(a, c), 2);
    assert_eq!(lev_distance(c, a), 2);
    assert_eq!(lev_distance(b, c), 1);
    assert_eq!(lev_distance(c, b), 1);
}
<commit_msg>Revert Iterator::min_by_key<commit_after>// Copyright 2012-2014 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

use ast::Name;
use std::cmp;
use parse::token::InternedString;

/// To find the Levenshtein distance between two strings
pub fn lev_distance(a: &str, b: &str) -> usize {
    // cases which don't require further computation
    if a.is_empty() {
        return b.chars().count();
    } else if b.is_empty() {
        return a.chars().count();
    }

    let mut dcol: Vec<_> = (0..b.len() + 1).collect();
    let mut t_last = 0;

    for (i, sc) in a.chars().enumerate() {
        let mut current = i;
        dcol[0] = current + 1;

        for (j, tc) in b.chars().enumerate() {
            let next = dcol[j + 1];
            if sc == tc {
                dcol[j + 1] = current;
            } else {
                dcol[j + 1] = cmp::min(current, next);
                dcol[j + 1] = cmp::min(dcol[j + 1], dcol[j]) + 1;
            }
            current = next;
            t_last = j;
        }
    } dcol[t_last + 1]
}

/// To find the best match for a given string from an iterator of names
/// As a loose rule to avoid the obviously incorrect suggestions, it takes
/// an optional limit for the maximum allowable edit distance, which defaults
/// to one-third of the given word
pub fn find_best_match_for_name<'a, T>(iter_names: T,
                                       lookup: &str,
                                       dist: Option<usize>) -> Option<InternedString>
    where T: Iterator<Item = &'a Name> {
    let max_dist = dist.map_or_else(|| cmp::max(lookup.len(), 3) / 3, |d| d);
    iter_names
    .filter_map(|name| {
        let dist = lev_distance(lookup, &name.as_str());
        match dist <= max_dist {    // filter the unwanted cases
            true => Some((name.as_str(), dist)),
            false => None,
        }
    })
    .min_by_key(|&(_, val)| val)    // extract the tuple containing the minimum edit distance
    .map(|(s, _)| s)                // and return only the string
}

#[test]
fn test_lev_distance() {
    use std::char::{from_u32, MAX};
    // Test bytelength agnosticity
    for c in (0..MAX as u32)
             .filter_map(|i| from_u32(i))
             .map(|i| i.to_string()) {
        assert_eq!(lev_distance(&c[..], &c[..]), 0);
    }

    let a = "\nMäry häd ä little lämb\n\nLittle lämb\n";
    let b = "\nMary häd ä little lämb\n\nLittle lämb\n";
    let c = "Mary häd ä little lämb\n\nLittle lämb\n";
    assert_eq!(lev_distance(a, b), 1);
    assert_eq!(lev_distance(b, a), 1);
    assert_eq!(lev_distance(a, c), 2);
    assert_eq!(lev_distance(c, a), 2);
    assert_eq!(lev_distance(b, c), 1);
    assert_eq!(lev_distance(c, b), 1);
}
<|endoftext|>


<commit_before>// Copyright (c) The Diem Core Contributors
// SPDX-License-Identifier: Apache-2.0

use super::{ChainInfo, CoreContext, Test};
use crate::Result;
use diem_sdk::client::BlockingClient;

/// The testing interface which defines a test written from the perspective of the Admin of the
/// network. This means that the test will have access to the Root account but do not control any
/// of the validators or full nodes running on the network.
pub trait AdminTest: Test {
    /// Executes the test against the given context.
    fn run<'t>(&self, ctx: &mut AdminContext<'t>) -> Result<()>;
}

#[derive(Debug)]
pub struct AdminContext<'t> {
    core: CoreContext,

    chain_info: ChainInfo<'t>,
}

impl<'t> AdminContext<'t> {
    pub fn new(core: CoreContext, chain_info: ChainInfo<'t>) -> Self {
        Self { core, chain_info }
    }

    pub fn core(&self) -> &CoreContext {
        &self.core
    }

    pub fn client(&self) -> BlockingClient {
        BlockingClient::new(&self.chain_info.json_rpc_url)
    }
}
<commit_msg>forge: add some helper methods to AdminContext<commit_after>// Copyright (c) The Diem Core Contributors
// SPDX-License-Identifier: Apache-2.0

use super::{ChainInfo, CoreContext, Test};
use crate::Result;
use diem_sdk::{client::BlockingClient, types::LocalAccount};

/// The testing interface which defines a test written from the perspective of the Admin of the
/// network. This means that the test will have access to the Root account but do not control any
/// of the validators or full nodes running on the network.
pub trait AdminTest: Test {
    /// Executes the test against the given context.
    fn run<'t>(&self, ctx: &mut AdminContext<'t>) -> Result<()>;
}

#[derive(Debug)]
pub struct AdminContext<'t> {
    core: CoreContext,

    chain_info: ChainInfo<'t>,
}

impl<'t> AdminContext<'t> {
    pub fn new(core: CoreContext, chain_info: ChainInfo<'t>) -> Self {
        Self { core, chain_info }
    }

    pub fn core(&self) -> &CoreContext {
        &self.core
    }

    pub fn rng(&mut self) -> &mut ::rand::rngs::StdRng {
        self.core.rng()
    }

    pub fn client(&self) -> BlockingClient {
        BlockingClient::new(&self.chain_info.json_rpc_url)
    }

    pub fn chain_info(&mut self) -> &mut ChainInfo<'t> {
        &mut self.chain_info
    }

    pub fn random_account(&mut self) -> LocalAccount {
        LocalAccount::generate(self.core.rng())
    }
}
<|endoftext|>


<commit_before>use std::collections::HashMap;

use library::*;
use nameutil;
use parser::is_empty_c_type;
use traits::MaybeRefAs;

impl Namespace {
    fn unresolved(&self) -> Vec<&str> {
        self.index
            .iter()
            .filter_map(|(name, &id)| if self.types[id as usize].is_none() {
                Some(&name[..])
            } else {
                None
            })
            .collect()
    }
}

type DetectedCTypes = HashMap<TypeId, String>;

impl Library {
    pub fn postprocessing(&mut self) {
        self.fix_gtype();
        self.check_resolved();
        self.fill_empty_signals_c_types();
        self.resolve_class_structs();
        self.correlate_class_structs();
        self.fix_fields();
    }

    fn fix_gtype(&mut self) {
        if let Some(ns_id) = self.find_namespace("GObject") {
            // hide the `GType` type alias in `GObject`
            self.add_type(ns_id, "Type", Type::Fundamental(Fundamental::Unsupported));
        }
    }

    fn check_resolved(&self) {
        let list: Vec<_> = self.index
            .iter()
            .flat_map(|(name, &id)| {
                let name = name.clone();
                self.namespace(id)
                    .unresolved()
                    .into_iter()
                    .map(move |s| format!("{}.{}", name, s))
            })
            .collect();

        if !list.is_empty() {
            panic!("Incomplete library, unresolved: {:?}", list);
        }
    }

    fn fill_empty_signals_c_types(&mut self) {
        let mut tids = Vec::new();
        let mut c_types = DetectedCTypes::new();
        for (ns_id, ns) in self.namespaces.iter().enumerate() {
            for (id, type_) in ns.types.iter().enumerate() {
                let type_ = type_.as_ref().unwrap(); //Always contains something
                let tid = TypeId {
                    ns_id: ns_id as u16,
                    id: id as u32,
                };
                match *type_ {
                    Type::Class(ref klass) => {
                        if self.detect_empty_signals_c_types(&klass.signals, &mut c_types) {
                            tids.push(tid);
                        }
                    }
                    Type::Interface(ref iface) => {
                        if self.detect_empty_signals_c_types(&iface.signals, &mut c_types) {
                            tids.push(tid);
                        }
                    }
                    _ => (),
                }
            }
        }

        fn update_empty_signals_c_types(signals: &mut [Signal], c_types: &DetectedCTypes) {
            for signal in signals {
                update_empty_signal_c_types(signal, c_types);
            }
        }

        fn update_empty_signal_c_types(signal: &mut Signal, c_types: &DetectedCTypes) {
            for par in &mut signal.parameters {
                update_empty_c_type(&mut par.c_type, par.typ, c_types);
            }
            update_empty_c_type(&mut signal.ret.c_type, signal.ret.typ, c_types);
        }

        fn update_empty_c_type(c_type: &mut String, tid: TypeId, c_types: &DetectedCTypes) {
            if !is_empty_c_type(c_type) {
                return;
            }
            if let Some(ref mut s) = c_types.get(&tid) {
                *c_type = s.clone();
            }
        }

        for tid in tids {
            match *self.type_mut(tid) {
                Type::Class(ref mut klass) => {
                    update_empty_signals_c_types(&mut klass.signals, &c_types)
                }
                Type::Interface(ref mut iface) => {
                    update_empty_signals_c_types(&mut iface.signals, &c_types)
                }
                _ => (),
            }
        }
    }

    fn detect_empty_signals_c_types(
        &self,
        signals: &[Signal],
        c_types: &mut DetectedCTypes,
    ) -> bool {
        let mut detected = false;
        for signal in signals {
            if self.detect_empty_signal_c_types(signal, c_types) {
                detected = true;
            }
        }
        detected
    }

    fn detect_empty_signal_c_types(&self, signal: &Signal, c_types: &mut DetectedCTypes) -> bool {
        let mut detected = false;
        for par in &signal.parameters {
            if self.detect_empty_c_type(&par.c_type, par.typ, c_types) {
                detected = true;
            }
        }
        if self.detect_empty_c_type(&signal.ret.c_type, signal.ret.typ, c_types) {
            detected = true;
        }
        detected
    }

    fn detect_empty_c_type(&self, c_type: &str, tid: TypeId, c_types: &mut DetectedCTypes) -> bool {
        if !is_empty_c_type(c_type) {
            return false;
        }
        if !c_types.contains_key(&tid) {
            if let Some(detected_c_type) = self.c_type_by_type_id(tid) {
                c_types.insert(tid, detected_c_type);
            }
        }
        true
    }

    fn c_type_by_type_id(&self, tid: TypeId) -> Option<String> {
        let type_ = self.type_(tid);
        type_
            .get_glib_name()
            .map(|glib_name| if self.is_referenced_type(type_) {
                format!("{}*", glib_name)
            } else {
                glib_name.to_string()
            })
    }

    fn is_referenced_type(&self, type_: &Type) -> bool {
        use library::Type::*;
        match *type_ {
            Alias(ref alias) => self.is_referenced_type(self.type_(alias.typ)),
            Record(..) | Union(..) | Class(..) | Interface(..) => true,
            _ => false,
        }
    }

    fn resolve_class_structs(&mut self) {
        // stores pairs of (gtype-struct-c-name, type-name)
        let mut structs_and_types = Vec::new();

        for (ns_id, ns) in self.namespaces.iter().enumerate() {
            for type_ in &ns.types {
                let type_ = type_.as_ref().unwrap(); //Always contains something

                if let Type::Record(ref record) = *type_ {
                    if let Some(ref struct_for) = record.gtype_struct_for {
                        if let Some(struct_for_tid) = self.find_type(ns_id as u16, struct_for) {
                            structs_and_types.push ((record.c_type.clone(), struct_for_tid));
                        }
                    }
                }
            }
        }

        for (gtype_struct_c_type, struct_for_tid) in structs_and_types {
            match *self.type_mut(struct_for_tid) {
                Type::Class(ref mut klass) => {
                    klass.c_class_type = Some(gtype_struct_c_type);
                },

                Type::Interface(ref mut iface) => {
                    iface.c_class_type = Some(gtype_struct_c_type);
                },

                ref x => unreachable!("Something other than a class or interface has a class struct: {:?}", x)
            }
        }
    }

    fn correlate_class_structs(&self) {
        for (ns_id, ns) in self.namespaces.iter().enumerate() {
            for type_ in &ns.types {
                let type_ = type_.as_ref().unwrap(); //Always contains something
                let name;
                let type_struct;
                let c_class_type;

                match *type_ {
                    Type::Class(ref klass) => {
                        name         = &klass.name;
                        type_struct  = &klass.type_struct;
                        c_class_type = &klass.c_class_type;
                    },

                    Type::Interface(ref iface) => {
                        name         = &iface.name;
                        type_struct  = &iface.type_struct;
                        c_class_type = &iface.c_class_type;
                    },

                    _ => { continue; }
                }

                if let Some(ref type_struct) = *type_struct {
                    let type_struct_tid = self.find_type(ns_id as u16, type_struct);
                    if type_struct_tid.is_none() {
                        panic!("\"{}\" has glib:type-struct=\"{}\" but there is no such record",
                               name,
                               type_struct);
                    }

                    let type_struct_type = self.type_(type_struct_tid.unwrap());

                    if let Type::Record(ref r) = *type_struct_type {
                        if r.gtype_struct_for.as_ref() != Some(name) {
                            if let Some(ref gtype_struct_for) = r.gtype_struct_for {
                                panic!("\"{}\" has glib:type-struct=\"{}\" but the corresponding record \"{}\" has glib:is-gtype-struct-for={:?}",
                                       name,
                                       type_struct,
                                       r.name,
                                       gtype_struct_for);
                            } else {
                                panic!("\"{}\" has glib:type-struct=\"{}\" but the corresponding record \"{}\" has no glib:is-gtype-struct-for attribute",
                                       name,
                                       type_struct,
                                       r.name);
                            }
                        }
                    } else {
                        panic!("Element with name=\"{}\" should be a record but it isn't",
                               type_struct);
                    }
                } else if let Some(ref c) = *c_class_type {
                    panic!("\"{}\" has no glib:type-struct but there is an element with glib:is-gtype-struct-for=\"{}\"",
                           name,
                           c);
                }
                // else both type_struct and c_class_type are None,
                // and that's fine because they don't reference each
                // other.
            }
        }
    }

    fn fix_fields(&mut self) {
        enum Action {
            SetCType(String),
            SetName(String),
        }
        let mut actions: Vec<(TypeId, usize, Action)> = Vec::new();
        for (ns_id, ns) in self.namespaces.iter().enumerate() {
            for (id, type_) in ns.types.iter().enumerate() {
                let type_ = type_.as_ref().unwrap(); //Always contains something
                let tid = TypeId {
                    ns_id: ns_id as u16,
                    id: id as u32,
                };
                match *type_ {
                    Type::Class(Class { ref name, ref fields, ..}) |
                    Type::Record(Record { ref name, ref fields, ..}) |
                    Type::Union(Union { ref name, ref fields, ..}) => {
                        for (fid, field) in fields.iter().enumerate() {
                            if nameutil::needs_mangling(&field.name) {
                                let new_name = nameutil::mangle_keywords(&*field.name).to_string();
                                actions.push((tid, fid, Action::SetName(new_name)));
                            }
                            if field.c_type.is_some() {
                                continue;
                            }
                            let field_type = self.type_(field.typ);
                            if let Some(_) = field_type.maybe_ref_as::<Function>() {
                                // Function pointers generally don't have c_type.
                                continue;
                            }
                            if let Some(c_type) = field_type.get_glib_name() {
                                actions.push((tid, fid, Action::SetCType(c_type.to_owned())));
                                continue;
                            }
                            if let Type::Fundamental(Fundamental::Pointer) = *field_type {
                                // For example SoupBuffer is missing c:type for data field.
                                actions.push((tid, fid, Action::SetCType("void*".to_owned())));
                                continue;
                            }
                            error!("Field `{}::{}` is missing c:type", name, &field.name);
                        }
                    },
                    _ => {},
                }
            }
        }
        for (tid, fid, action) in actions {
            match *self.type_mut(tid) {
                Type::Class(Class { ref name, ref mut fields, ..}) |
                Type::Record(Record { ref name, ref mut fields, ..}) |
                Type::Union(Union { ref name, ref mut fields, ..}) => {
                    match action {
                        Action::SetCType(c_type) => {
                            warn!("Field `{}::{}` missing c:type assumed to be `{}`",
                                  name, &fields[fid].name, c_type);
                            fields[fid].c_type = Some(c_type);
                        }
                        Action::SetName(name) => fields[fid].name = name,
                    }
                },
                _ => unreachable!("Expected class, record or union"),
            }
        }
    }

}
<commit_msg>Remove empty line.<commit_after>use std::collections::HashMap;

use library::*;
use nameutil;
use parser::is_empty_c_type;
use traits::MaybeRefAs;

impl Namespace {
    fn unresolved(&self) -> Vec<&str> {
        self.index
            .iter()
            .filter_map(|(name, &id)| if self.types[id as usize].is_none() {
                Some(&name[..])
            } else {
                None
            })
            .collect()
    }
}

type DetectedCTypes = HashMap<TypeId, String>;

impl Library {
    pub fn postprocessing(&mut self) {
        self.fix_gtype();
        self.check_resolved();
        self.fill_empty_signals_c_types();
        self.resolve_class_structs();
        self.correlate_class_structs();
        self.fix_fields();
    }

    fn fix_gtype(&mut self) {
        if let Some(ns_id) = self.find_namespace("GObject") {
            // hide the `GType` type alias in `GObject`
            self.add_type(ns_id, "Type", Type::Fundamental(Fundamental::Unsupported));
        }
    }

    fn check_resolved(&self) {
        let list: Vec<_> = self.index
            .iter()
            .flat_map(|(name, &id)| {
                let name = name.clone();
                self.namespace(id)
                    .unresolved()
                    .into_iter()
                    .map(move |s| format!("{}.{}", name, s))
            })
            .collect();

        if !list.is_empty() {
            panic!("Incomplete library, unresolved: {:?}", list);
        }
    }

    fn fill_empty_signals_c_types(&mut self) {
        let mut tids = Vec::new();
        let mut c_types = DetectedCTypes::new();
        for (ns_id, ns) in self.namespaces.iter().enumerate() {
            for (id, type_) in ns.types.iter().enumerate() {
                let type_ = type_.as_ref().unwrap(); //Always contains something
                let tid = TypeId {
                    ns_id: ns_id as u16,
                    id: id as u32,
                };
                match *type_ {
                    Type::Class(ref klass) => {
                        if self.detect_empty_signals_c_types(&klass.signals, &mut c_types) {
                            tids.push(tid);
                        }
                    }
                    Type::Interface(ref iface) => {
                        if self.detect_empty_signals_c_types(&iface.signals, &mut c_types) {
                            tids.push(tid);
                        }
                    }
                    _ => (),
                }
            }
        }

        fn update_empty_signals_c_types(signals: &mut [Signal], c_types: &DetectedCTypes) {
            for signal in signals {
                update_empty_signal_c_types(signal, c_types);
            }
        }

        fn update_empty_signal_c_types(signal: &mut Signal, c_types: &DetectedCTypes) {
            for par in &mut signal.parameters {
                update_empty_c_type(&mut par.c_type, par.typ, c_types);
            }
            update_empty_c_type(&mut signal.ret.c_type, signal.ret.typ, c_types);
        }

        fn update_empty_c_type(c_type: &mut String, tid: TypeId, c_types: &DetectedCTypes) {
            if !is_empty_c_type(c_type) {
                return;
            }
            if let Some(ref mut s) = c_types.get(&tid) {
                *c_type = s.clone();
            }
        }

        for tid in tids {
            match *self.type_mut(tid) {
                Type::Class(ref mut klass) => {
                    update_empty_signals_c_types(&mut klass.signals, &c_types)
                }
                Type::Interface(ref mut iface) => {
                    update_empty_signals_c_types(&mut iface.signals, &c_types)
                }
                _ => (),
            }
        }
    }

    fn detect_empty_signals_c_types(
        &self,
        signals: &[Signal],
        c_types: &mut DetectedCTypes,
    ) -> bool {
        let mut detected = false;
        for signal in signals {
            if self.detect_empty_signal_c_types(signal, c_types) {
                detected = true;
            }
        }
        detected
    }

    fn detect_empty_signal_c_types(&self, signal: &Signal, c_types: &mut DetectedCTypes) -> bool {
        let mut detected = false;
        for par in &signal.parameters {
            if self.detect_empty_c_type(&par.c_type, par.typ, c_types) {
                detected = true;
            }
        }
        if self.detect_empty_c_type(&signal.ret.c_type, signal.ret.typ, c_types) {
            detected = true;
        }
        detected
    }

    fn detect_empty_c_type(&self, c_type: &str, tid: TypeId, c_types: &mut DetectedCTypes) -> bool {
        if !is_empty_c_type(c_type) {
            return false;
        }
        if !c_types.contains_key(&tid) {
            if let Some(detected_c_type) = self.c_type_by_type_id(tid) {
                c_types.insert(tid, detected_c_type);
            }
        }
        true
    }

    fn c_type_by_type_id(&self, tid: TypeId) -> Option<String> {
        let type_ = self.type_(tid);
        type_
            .get_glib_name()
            .map(|glib_name| if self.is_referenced_type(type_) {
                format!("{}*", glib_name)
            } else {
                glib_name.to_string()
            })
    }

    fn is_referenced_type(&self, type_: &Type) -> bool {
        use library::Type::*;
        match *type_ {
            Alias(ref alias) => self.is_referenced_type(self.type_(alias.typ)),
            Record(..) | Union(..) | Class(..) | Interface(..) => true,
            _ => false,
        }
    }

    fn resolve_class_structs(&mut self) {
        // stores pairs of (gtype-struct-c-name, type-name)
        let mut structs_and_types = Vec::new();

        for (ns_id, ns) in self.namespaces.iter().enumerate() {
            for type_ in &ns.types {
                let type_ = type_.as_ref().unwrap(); //Always contains something

                if let Type::Record(ref record) = *type_ {
                    if let Some(ref struct_for) = record.gtype_struct_for {
                        if let Some(struct_for_tid) = self.find_type(ns_id as u16, struct_for) {
                            structs_and_types.push ((record.c_type.clone(), struct_for_tid));
                        }
                    }
                }
            }
        }

        for (gtype_struct_c_type, struct_for_tid) in structs_and_types {
            match *self.type_mut(struct_for_tid) {
                Type::Class(ref mut klass) => {
                    klass.c_class_type = Some(gtype_struct_c_type);
                },

                Type::Interface(ref mut iface) => {
                    iface.c_class_type = Some(gtype_struct_c_type);
                },

                ref x => unreachable!("Something other than a class or interface has a class struct: {:?}", x)
            }
        }
    }

    fn correlate_class_structs(&self) {
        for (ns_id, ns) in self.namespaces.iter().enumerate() {
            for type_ in &ns.types {
                let type_ = type_.as_ref().unwrap(); //Always contains something
                let name;
                let type_struct;
                let c_class_type;

                match *type_ {
                    Type::Class(ref klass) => {
                        name         = &klass.name;
                        type_struct  = &klass.type_struct;
                        c_class_type = &klass.c_class_type;
                    },

                    Type::Interface(ref iface) => {
                        name         = &iface.name;
                        type_struct  = &iface.type_struct;
                        c_class_type = &iface.c_class_type;
                    },

                    _ => { continue; }
                }

                if let Some(ref type_struct) = *type_struct {
                    let type_struct_tid = self.find_type(ns_id as u16, type_struct);
                    if type_struct_tid.is_none() {
                        panic!("\"{}\" has glib:type-struct=\"{}\" but there is no such record",
                               name,
                               type_struct);
                    }

                    let type_struct_type = self.type_(type_struct_tid.unwrap());

                    if let Type::Record(ref r) = *type_struct_type {
                        if r.gtype_struct_for.as_ref() != Some(name) {
                            if let Some(ref gtype_struct_for) = r.gtype_struct_for {
                                panic!("\"{}\" has glib:type-struct=\"{}\" but the corresponding record \"{}\" has glib:is-gtype-struct-for={:?}",
                                       name,
                                       type_struct,
                                       r.name,
                                       gtype_struct_for);
                            } else {
                                panic!("\"{}\" has glib:type-struct=\"{}\" but the corresponding record \"{}\" has no glib:is-gtype-struct-for attribute",
                                       name,
                                       type_struct,
                                       r.name);
                            }
                        }
                    } else {
                        panic!("Element with name=\"{}\" should be a record but it isn't",
                               type_struct);
                    }
                } else if let Some(ref c) = *c_class_type {
                    panic!("\"{}\" has no glib:type-struct but there is an element with glib:is-gtype-struct-for=\"{}\"",
                           name,
                           c);
                }
                // else both type_struct and c_class_type are None,
                // and that's fine because they don't reference each
                // other.
            }
        }
    }

    fn fix_fields(&mut self) {
        enum Action {
            SetCType(String),
            SetName(String),
        }
        let mut actions: Vec<(TypeId, usize, Action)> = Vec::new();
        for (ns_id, ns) in self.namespaces.iter().enumerate() {
            for (id, type_) in ns.types.iter().enumerate() {
                let type_ = type_.as_ref().unwrap(); //Always contains something
                let tid = TypeId {
                    ns_id: ns_id as u16,
                    id: id as u32,
                };
                match *type_ {
                    Type::Class(Class { ref name, ref fields, ..}) |
                    Type::Record(Record { ref name, ref fields, ..}) |
                    Type::Union(Union { ref name, ref fields, ..}) => {
                        for (fid, field) in fields.iter().enumerate() {
                            if nameutil::needs_mangling(&field.name) {
                                let new_name = nameutil::mangle_keywords(&*field.name).to_string();
                                actions.push((tid, fid, Action::SetName(new_name)));
                            }
                            if field.c_type.is_some() {
                                continue;
                            }
                            let field_type = self.type_(field.typ);
                            if let Some(_) = field_type.maybe_ref_as::<Function>() {
                                // Function pointers generally don't have c_type.
                                continue;
                            }
                            if let Some(c_type) = field_type.get_glib_name() {
                                actions.push((tid, fid, Action::SetCType(c_type.to_owned())));
                                continue;
                            }
                            if let Type::Fundamental(Fundamental::Pointer) = *field_type {
                                // For example SoupBuffer is missing c:type for data field.
                                actions.push((tid, fid, Action::SetCType("void*".to_owned())));
                                continue;
                            }
                            error!("Field `{}::{}` is missing c:type", name, &field.name);
                        }
                    },
                    _ => {},
                }
            }
        }
        for (tid, fid, action) in actions {
            match *self.type_mut(tid) {
                Type::Class(Class { ref name, ref mut fields, ..}) |
                Type::Record(Record { ref name, ref mut fields, ..}) |
                Type::Union(Union { ref name, ref mut fields, ..}) => {
                    match action {
                        Action::SetCType(c_type) => {
                            warn!("Field `{}::{}` missing c:type assumed to be `{}`",
                                  name, &fields[fid].name, c_type);
                            fields[fid].c_type = Some(c_type);
                        }
                        Action::SetName(name) => fields[fid].name = name,
                    }
                },
                _ => unreachable!("Expected class, record or union"),
            }
        }
    }
}
<|endoftext|>


<commit_before>// Copyright (c) The Libra Core Contributors
// SPDX-License-Identifier: Apache-2.0

use crate::chained_bft::{
    common::{Author, Payload, Round},
    consensus_types::{block::Block, sync_info::SyncInfo},
};
use failure::prelude::*;
use network::proto::Proposal as ProtoProposal;
use proto_conv::{FromProto, IntoProto};
use std::fmt;
use types::crypto_proxies::ValidatorVerifier;

/// ProposalMsg contains the required information for the proposer election protocol to make its
/// choice (typically depends on round and proposer info).
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct ProposalMsg<T> {
    proposal: Block<T>,
    sync_info: SyncInfo,
}

/// A ProposalMsg is only accessible after verifying the signatures of a ProposalUncheckedSignatures
/// via the `validate_signatures` function.
pub struct ProposalUncheckedSignatures<T>(ProposalMsg<T>);

impl<T: Payload> FromProto for ProposalUncheckedSignatures<T> {
    type ProtoType = ProtoProposal;

    fn from_proto(mut object: Self::ProtoType) -> Result<Self> {
        let proposal = Block::<T>::from_proto(object.take_proposed_block())?;
        let sync_info = SyncInfo::from_proto(object.take_sync_info())?;
        Ok(ProposalUncheckedSignatures(ProposalMsg::new(
            proposal, sync_info,
        )))
    }
}

#[cfg(any(test, feature = "fuzzing"))]
impl<T: Payload> From<ProposalUncheckedSignatures<T>> for ProposalMsg<T> {
    fn from(proposal: ProposalUncheckedSignatures<T>) -> Self {
        proposal.0
    }
}

impl<T: Payload> ProposalUncheckedSignatures<T> {
    /// Validates the signatures of the proposal. This includes the leader's signature over the
    /// block and the QC, the timeout certificate signatures and the highest_ledger_info signatures.
    pub fn validate_signatures(self, validator: &ValidatorVerifier) -> Result<ProposalMsg<T>> {
        // verify block leader's signature and QC
        self.0
            .proposal
            .validate_signatures(validator)
            .map_err(|e| format_err!("{:?}", e))?;
        // if there is a timeout certificate, verify its signatures
        if let Some(tc) = self.0.sync_info.highest_timeout_certificate() {
            tc.verify(validator).map_err(|e| format_err!("{:?}", e))?;
        }
        // verify the QC signatures of highest_ledger_info
        self.0
            .sync_info
            .highest_ledger_info()
            .verify(validator)
            .map_err(|e| format_err!("{:?}", e))?;
        // return proposal
        Ok(self.0)
    }
}

impl<T: Payload> ProposalMsg<T> {
    /// Creates a new proposal.
    pub fn new(proposal: Block<T>, sync_info: SyncInfo) -> Self {
        Self {
            proposal,
            sync_info,
        }
    }

    /// Verifies that the ProposalMsg is well-formed.
    pub fn verify_well_formed(self) -> Result<Self> {
        ensure!(
            !self.proposal.is_nil_block(),
            "Proposal {} for a NIL block",
            self.proposal
        );
        self.proposal
            .verify_well_formed()
            .with_context(|e| format!("Fail to verify ProposalMsg's block: {:}", e))?;
        ensure!(
            self.proposal.round() > 0,
            "Proposal for {} has an incorrect round of 0",
            self.proposal,
        );
        ensure!(
            self.proposal.parent_id() == self.sync_info.highest_quorum_cert().certified_block_id(),
            "Proposal HQC in SyncInfo certifies {}, but block parent id is {}",
            self.sync_info.highest_quorum_cert().certified_block_id(),
            self.proposal.parent_id(),
        );
        let previous_round = self.proposal.round() - 1;
        if let Some(tc) = self.sync_info.highest_timeout_certificate() {
            let previous_round = self.proposal.round() - 1;
            ensure!(
                tc.round() == previous_round,
                "Proposal for {} has a timeout certificate with an incorrect round={}",
                self.proposal,
                tc.round(),
            );
            ensure!(
                self.proposal.quorum_cert().certified_block_round() != tc.round(),
                "Proposal for {} has a timeout certificate and a quorum certificate that have the same round",
                self.proposal,
            );
        } else {
            ensure!(
                self.proposal.quorum_cert().certified_block_round() == previous_round,
                "Proposal for {} has a timeout certificate with an incorrect round={}",
                self.proposal,
                self.proposal.quorum_cert().certified_block_round(),
            );
        }
        ensure!(
            self.proposal.author().is_some(),
            "Proposal {} does not define an author",
            self.proposal
        );
        Ok(self)
    }

    pub fn proposal(&self) -> &Block<T> {
        &self.proposal
    }

    pub fn take_proposal(self) -> Block<T> {
        self.proposal
    }

    pub fn sync_info(&self) -> &SyncInfo {
        &self.sync_info
    }

    pub fn round(&self) -> Round {
        self.proposal.round()
    }

    pub fn proposer(&self) -> Author {
        self.proposal
            .author()
            .expect("Proposal should be verified having an author")
    }
}

impl<T: Payload> fmt::Display for ProposalMsg<T> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        let author = match self.proposal.author() {
            Some(author) => author.short_str(),
            None => String::from("NIL"),
        };
        write!(f, "[proposal {} from {}]", self.proposal, author,)
    }
}

impl<T: Payload> IntoProto for ProposalMsg<T> {
    type ProtoType = ProtoProposal;

    fn into_proto(self) -> Self::ProtoType {
        let mut proto = Self::ProtoType::new();
        proto.set_proposed_block(self.proposal.into_proto());
        proto.set_sync_info(self.sync_info.into_proto());
        proto
    }
}
<commit_msg>[consensus] impl conversions from/to prost proto and Proposal<commit_after>// Copyright (c) The Libra Core Contributors
// SPDX-License-Identifier: Apache-2.0

use crate::chained_bft::{
    common::{Author, Payload, Round},
    consensus_types::{block::Block, sync_info::SyncInfo},
};
use failure::prelude::*;
use network::proto::Proposal as ProtoProposal;
use proto_conv::{FromProto, IntoProto};
use std::convert::{TryFrom, TryInto};
use std::fmt;
use types::crypto_proxies::ValidatorVerifier;

/// ProposalMsg contains the required information for the proposer election protocol to make its
/// choice (typically depends on round and proposer info).
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct ProposalMsg<T> {
    proposal: Block<T>,
    sync_info: SyncInfo,
}

/// A ProposalMsg is only accessible after verifying the signatures of a ProposalUncheckedSignatures
/// via the `validate_signatures` function.
pub struct ProposalUncheckedSignatures<T>(ProposalMsg<T>);

impl<T: Payload> FromProto for ProposalUncheckedSignatures<T> {
    type ProtoType = ProtoProposal;

    fn from_proto(mut object: Self::ProtoType) -> Result<Self> {
        let proposal = Block::<T>::from_proto(object.take_proposed_block())?;
        let sync_info = SyncInfo::from_proto(object.take_sync_info())?;
        Ok(ProposalUncheckedSignatures(ProposalMsg::new(
            proposal, sync_info,
        )))
    }
}

impl<T: Payload> TryFrom<network::proto::consensus_prost::Proposal>
    for ProposalUncheckedSignatures<T>
{
    type Error = failure::Error;

    fn try_from(proto: network::proto::consensus_prost::Proposal) -> failure::Result<Self> {
        let proposal = proto
            .proposed_block
            .ok_or_else(|| format_err!("Missing proposed_block"))?
            .try_into()?;
        let sync_info = proto
            .sync_info
            .ok_or_else(|| format_err!("Missing sync_info"))?
            .try_into()?;
        Ok(ProposalUncheckedSignatures(ProposalMsg::new(
            proposal, sync_info,
        )))
    }
}

#[cfg(any(test, feature = "fuzzing"))]
impl<T: Payload> From<ProposalUncheckedSignatures<T>> for ProposalMsg<T> {
    fn from(proposal: ProposalUncheckedSignatures<T>) -> Self {
        proposal.0
    }
}

impl<T: Payload> ProposalUncheckedSignatures<T> {
    /// Validates the signatures of the proposal. This includes the leader's signature over the
    /// block and the QC, the timeout certificate signatures and the highest_ledger_info signatures.
    pub fn validate_signatures(self, validator: &ValidatorVerifier) -> Result<ProposalMsg<T>> {
        // verify block leader's signature and QC
        self.0
            .proposal
            .validate_signatures(validator)
            .map_err(|e| format_err!("{:?}", e))?;
        // if there is a timeout certificate, verify its signatures
        if let Some(tc) = self.0.sync_info.highest_timeout_certificate() {
            tc.verify(validator).map_err(|e| format_err!("{:?}", e))?;
        }
        // verify the QC signatures of highest_ledger_info
        self.0
            .sync_info
            .highest_ledger_info()
            .verify(validator)
            .map_err(|e| format_err!("{:?}", e))?;
        // return proposal
        Ok(self.0)
    }
}

impl<T: Payload> ProposalMsg<T> {
    /// Creates a new proposal.
    pub fn new(proposal: Block<T>, sync_info: SyncInfo) -> Self {
        Self {
            proposal,
            sync_info,
        }
    }

    /// Verifies that the ProposalMsg is well-formed.
    pub fn verify_well_formed(self) -> Result<Self> {
        ensure!(
            !self.proposal.is_nil_block(),
            "Proposal {} for a NIL block",
            self.proposal
        );
        self.proposal
            .verify_well_formed()
            .with_context(|e| format!("Fail to verify ProposalMsg's block: {:}", e))?;
        ensure!(
            self.proposal.round() > 0,
            "Proposal for {} has an incorrect round of 0",
            self.proposal,
        );
        ensure!(
            self.proposal.parent_id() == self.sync_info.highest_quorum_cert().certified_block_id(),
            "Proposal HQC in SyncInfo certifies {}, but block parent id is {}",
            self.sync_info.highest_quorum_cert().certified_block_id(),
            self.proposal.parent_id(),
        );
        let previous_round = self.proposal.round() - 1;
        if let Some(tc) = self.sync_info.highest_timeout_certificate() {
            let previous_round = self.proposal.round() - 1;
            ensure!(
                tc.round() == previous_round,
                "Proposal for {} has a timeout certificate with an incorrect round={}",
                self.proposal,
                tc.round(),
            );
            ensure!(
                self.proposal.quorum_cert().certified_block_round() != tc.round(),
                "Proposal for {} has a timeout certificate and a quorum certificate that have the same round",
                self.proposal,
            );
        } else {
            ensure!(
                self.proposal.quorum_cert().certified_block_round() == previous_round,
                "Proposal for {} has a timeout certificate with an incorrect round={}",
                self.proposal,
                self.proposal.quorum_cert().certified_block_round(),
            );
        }
        ensure!(
            self.proposal.author().is_some(),
            "Proposal {} does not define an author",
            self.proposal
        );
        Ok(self)
    }

    pub fn proposal(&self) -> &Block<T> {
        &self.proposal
    }

    pub fn take_proposal(self) -> Block<T> {
        self.proposal
    }

    pub fn sync_info(&self) -> &SyncInfo {
        &self.sync_info
    }

    pub fn round(&self) -> Round {
        self.proposal.round()
    }

    pub fn proposer(&self) -> Author {
        self.proposal
            .author()
            .expect("Proposal should be verified having an author")
    }
}

impl<T: Payload> fmt::Display for ProposalMsg<T> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        let author = match self.proposal.author() {
            Some(author) => author.short_str(),
            None => String::from("NIL"),
        };
        write!(f, "[proposal {} from {}]", self.proposal, author,)
    }
}

impl<T: Payload> IntoProto for ProposalMsg<T> {
    type ProtoType = ProtoProposal;

    fn into_proto(self) -> Self::ProtoType {
        let mut proto = Self::ProtoType::new();
        proto.set_proposed_block(self.proposal.into_proto());
        proto.set_sync_info(self.sync_info.into_proto());
        proto
    }
}

impl<T: Payload> From<ProposalMsg<T>> for network::proto::consensus_prost::Proposal {
    fn from(proposal: ProposalMsg<T>) -> Self {
        Self {
            proposed_block: Some(proposal.proposal.into()),
            sync_info: Some(proposal.sync_info.into()),
        }
    }
}
<|endoftext|>


<commit_before>/*!
`HMAC-SHA-256` `HMAC-SHA-256` is conjectured to meet the standard notion of
unforgeability.
*/
use std::libc::{c_ulonglong, c_int};
use std::vec::raw::{to_ptr, to_mut_ptr};
use randombytes::randombytes_into;
use crypto::verify::verify_32;

#[link(name = "sodium")]
#[link_args = "-lsodium"]
extern {
    fn crypto_auth_hmacsha256(a: *mut u8,
                                 m: *u8,
                                 mlen: c_ulonglong,
                                 k: *u8) -> c_int;
    fn crypto_auth_hmacsha256_verify(a: *u8,
                                        m: *u8,
                                        mlen: c_ulonglong,
                                        k: *u8) -> c_int;
}

pub static KEYBYTES: uint = 32;
pub static TAGBYTES: uint = 32;

/**
 * Authentication `Key`
 *
 * When a `Key` goes out of scope its contents
 * will be zeroed out
 */
pub struct Key([u8, ..KEYBYTES]);

impl Drop for Key {
    fn drop(&mut self) {
        for e in self.mut_iter() { *e = 0 }
    }
}

/**
  * Authentication `Tag`
  *
  * The tag implements the traits `TotalEq` and `Eq` using constant-time
  * comparison functions. See `sodiumoxide::crypto::verify::verify_32`
  */
pub struct Tag([u8, ..TAGBYTES]);
impl TotalEq for Tag {
    fn equals(&self, other: &Tag) -> bool {
        verify_32(&**self, &**other)
    }
}
impl Eq for Tag {
    fn eq(&self, other: &Tag) -> bool {
        verify_32(&**self, &**other)
    }
}

/**
 * `gen_key()` randomly generates a key for authentication
 *
 * THREAD SAFETY: `gen_key()` is thread-safe provided that you have
 * called `sodiumoxide::init()` once before using any other function
 * from sodiumoxide.
 */
pub fn gen_key() -> ~Key {
    let mut key = ~Key([0, ..KEYBYTES]);
    randombytes_into(**key);
    key
}

/**
 * `authenticate()` authenticates a message `m` using a secret key `k`.
 * The function returns an authenticator tag.
 */
#[fixed_stack_segment]
pub fn authenticate(m: &[u8], k: &Key) -> ~Tag {
    unsafe {
        let mut tag = ~Tag([0, ..TAGBYTES]);
        crypto_auth_hmacsha256(to_mut_ptr(**tag),
                               to_ptr(m),
                               m.len() as c_ulonglong,
                               to_ptr(**k));
        tag
    }
}

/**
 * `verify()` returns `true` if `tag` is a correct authenticator of message `m`
 * under a secret key `k`. Otherwise it returns false.
 */
#[fixed_stack_segment]
pub fn verify(tag: &Tag, m: &[u8], k: &Key) -> bool {
    unsafe {
        crypto_auth_hmacsha256_verify(to_ptr(**tag),
                                      to_ptr(m),
                                      m.len() as c_ulonglong,
                                      to_ptr(**k)) == 0
    }
}

#[test]
fn test_auth_verify() {
    use randombytes::randombytes;
    for i in range(0, 256) {
        let k = gen_key();
        let m = randombytes(i as uint);
        let tag = authenticate(m, k);
        assert!(verify(tag, m, k));
    }
}

#[test]
fn test_auth_verify_tamper() {
    use randombytes::randombytes;
    for i in range(0, 32) {
        let k = gen_key();
        let mut m = randombytes(i as uint);
        let mut tag = authenticate(m, k);
        for j in range(0, m.len()) {
            m[j] ^= 0x20;
            assert!(!verify(tag, m, k));
            m[j] ^= 0x20;
        }
        for j in range(0, tag.len()) {
            tag[j] ^= 0x20;
            assert!(!verify(tag, m, k));
            tag[j] ^= 0x20;
        }
    }
}
<commit_msg>added test vector for hmacsha256<commit_after>/*!
`HMAC-SHA-256` `HMAC-SHA-256` is conjectured to meet the standard notion of
unforgeability.
*/
use std::libc::{c_ulonglong, c_int};
use std::vec::raw::{to_ptr, to_mut_ptr};
use randombytes::randombytes_into;
use crypto::verify::verify_32;

#[link(name = "sodium")]
#[link_args = "-lsodium"]
extern {
    fn crypto_auth_hmacsha256(a: *mut u8,
                                 m: *u8,
                                 mlen: c_ulonglong,
                                 k: *u8) -> c_int;
    fn crypto_auth_hmacsha256_verify(a: *u8,
                                        m: *u8,
                                        mlen: c_ulonglong,
                                        k: *u8) -> c_int;
}

pub static KEYBYTES: uint = 32;
pub static TAGBYTES: uint = 32;

/**
 * Authentication `Key`
 *
 * When a `Key` goes out of scope its contents
 * will be zeroed out
 */
pub struct Key([u8, ..KEYBYTES]);

impl Drop for Key {
    fn drop(&mut self) {
        for e in self.mut_iter() { *e = 0 }
    }
}

/**
  * Authentication `Tag`
  *
  * The tag implements the traits `TotalEq` and `Eq` using constant-time
  * comparison functions. See `sodiumoxide::crypto::verify::verify_32`
  */
pub struct Tag([u8, ..TAGBYTES]);
impl TotalEq for Tag {
    fn equals(&self, other: &Tag) -> bool {
        verify_32(&**self, &**other)
    }
}
impl Eq for Tag {
    fn eq(&self, other: &Tag) -> bool {
        verify_32(&**self, &**other)
    }
}

/**
 * `gen_key()` randomly generates a key for authentication
 *
 * THREAD SAFETY: `gen_key()` is thread-safe provided that you have
 * called `sodiumoxide::init()` once before using any other function
 * from sodiumoxide.
 */
pub fn gen_key() -> ~Key {
    let mut key = ~Key([0, ..KEYBYTES]);
    randombytes_into(**key);
    key
}

/**
 * `authenticate()` authenticates a message `m` using a secret key `k`.
 * The function returns an authenticator tag.
 */
#[fixed_stack_segment]
pub fn authenticate(m: &[u8], k: &Key) -> ~Tag {
    unsafe {
        let mut tag = ~Tag([0, ..TAGBYTES]);
        crypto_auth_hmacsha256(to_mut_ptr(**tag),
                               to_ptr(m),
                               m.len() as c_ulonglong,
                               to_ptr(**k));
        tag
    }
}

/**
 * `verify()` returns `true` if `tag` is a correct authenticator of message `m`
 * under a secret key `k`. Otherwise it returns false.
 */
#[fixed_stack_segment]
pub fn verify(tag: &Tag, m: &[u8], k: &Key) -> bool {
    unsafe {
        crypto_auth_hmacsha256_verify(to_ptr(**tag),
                                      to_ptr(m),
                                      m.len() as c_ulonglong,
                                      to_ptr(**k)) == 0
    }
}

#[test]
fn test_auth_verify() {
    use randombytes::randombytes;
    for i in range(0, 256) {
        let k = gen_key();
        let m = randombytes(i as uint);
        let tag = authenticate(m, k);
        assert!(verify(tag, m, k));
    }
}

#[test]
fn test_auth_verify_tamper() {
    use randombytes::randombytes;
    for i in range(0, 32) {
        let k = gen_key();
        let mut m = randombytes(i as uint);
        let mut tag = authenticate(m, k);
        for j in range(0, m.len()) {
            m[j] ^= 0x20;
            assert!(!verify(tag, m, k));
            m[j] ^= 0x20;
        }
        for j in range(0, tag.len()) {
            tag[j] ^= 0x20;
            assert!(!verify(tag, m, k));
            tag[j] ^= 0x20;
        }
    }
}

#[test]
fn test_vector_1() {
    // corresponding to tests/auth2.c from NaCl
    /* "Test Case AUTH256-4 from RFC 4868 */
    let key = Key([0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08
                  ,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f,0x10
                  ,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18
                  ,0x19,0x1a,0x1b,0x1c,0x1d,0x1e,0x1f,0x20]);
    let c = [0xcd,0xcd,0xcd,0xcd,0xcd,0xcd,0xcd,0xcd
            ,0xcd,0xcd,0xcd,0xcd,0xcd,0xcd,0xcd,0xcd
            ,0xcd,0xcd,0xcd,0xcd,0xcd,0xcd,0xcd,0xcd
            ,0xcd,0xcd,0xcd,0xcd,0xcd,0xcd,0xcd,0xcd
            ,0xcd,0xcd,0xcd,0xcd,0xcd,0xcd,0xcd,0xcd
            ,0xcd,0xcd,0xcd,0xcd,0xcd,0xcd,0xcd,0xcd
            ,0xcd,0xcd];
    let a_expected = Tag([0x37,0x2e,0xfc,0xf9,0xb4,0x0b,0x35,0xc2
                         ,0x11,0x5b,0x13,0x46,0x90,0x3d,0x2e,0xf4
                         ,0x2f,0xce,0xd4,0x6f,0x08,0x46,0xe7,0x25
                         ,0x7b,0xb1,0x56,0xd3,0xd7,0xb3,0x0d,0x3f]);
    let a = authenticate(c, &key);
    assert!(*a == a_expected);
}
<|endoftext|>


<commit_before>use parser::Block;
use parser::inline::parse_inline_elements;
use regex::Regex;

pub fn parse_paragraph(lines: &[&str]) -> Option<(Block, usize)> {
    let pattern = Regex::new("(?:p\\. )?").unwrap();
    let mut strings = Vec::new();
    let mut cur_line = 1;

    if pattern.is_match(lines[0]) {
        let caps = pattern.captures(lines[0]).unwrap();

        strings.push((&lines[0][caps.at(0).unwrap().len()..]).to_string());

        for line in &lines[1..] {
            cur_line += 1;
            if line.is_empty() {
                break;
            }
            strings.push(line.to_string());
        }

        Some(
            (Block::Paragraph {
                elements: parse_inline_elements(&*strings.join("\n"))
            },
            cur_line
        ))
    } else {
        None
    }
}
<commit_msg>Fix parsing newlines in paragraph parser<commit_after>use parser::Block;
use parser::inline::parse_inline_elements;
use regex::Regex;

pub fn parse_paragraph(lines: &[&str]) -> Option<(Block, usize)> {
    let pattern = Regex::new("(?:p\\. )?").unwrap();
    let pos = lines.iter().position(|el| !el.is_empty());
    let mut cur_line = match pos {
        Some(value) => {
            match value {
                0 => 1,
                _ => value + 1
            }
        }
        None => 1
    };
    let lines = match pos {
        Some(value) => &lines[value..],
        None => lines
    };
    let mut strings = Vec::new();

    if pattern.is_match(lines[0]) {
        let caps = pattern.captures(lines[0]).unwrap();

        strings.push((&lines[0][caps.at(0).unwrap().len()..]).to_string());

        for line in &lines[1..] {
            cur_line += 1;
            if line.is_empty() {
                break;
            }
            strings.push(line.to_string());
        }

        Some(
            (Block::Paragraph {
                elements: parse_inline_elements(&*strings.join("\n"))
            },
            cur_line
        ))
    } else {
        None
    }
}
<|endoftext|>


<commit_before>// Copyright (c) 2016-2020 Fabian Schuiki

use moore_common::source::get_source_manager;
use moore_svlog_syntax::{lexer::Lexer, parser, preproc::Preprocessor};

pub(crate) use moore_svlog_syntax::ast;

pub(crate) fn parse(input: &str) -> ast::Root {
    use std::cell::Cell;
    thread_local!(static INDEX: Cell<usize> = Cell::new(0));
    let sm = get_source_manager();
    let idx = INDEX.with(|i| {
        let v = i.get();
        i.set(v + 1);
        v
    });
    let source = sm.add(&format!("test_{}.sv", idx), input);
    let pp = Preprocessor::new(source, &[], &[]);
    let lexer = Lexer::new(pp);
    parser::parse(lexer).unwrap()
}
<commit_msg>svlog: syntax: Fix minor test typo<commit_after>// Copyright (c) 2016-2020 Fabian Schuiki

use moore_common::source::get_source_manager;
use moore_svlog_syntax::{lexer::Lexer, parser, preproc::Preprocessor};

pub(crate) use moore_svlog_syntax::ast;

pub(crate) fn parse(input: &str) -> ast::SourceFile {
    use std::cell::Cell;
    thread_local!(static INDEX: Cell<usize> = Cell::new(0));
    let sm = get_source_manager();
    let idx = INDEX.with(|i| {
        let v = i.get();
        i.set(v + 1);
        v
    });
    let source = sm.add(&format!("test_{}.sv", idx), input);
    let pp = Preprocessor::new(source, &[], &[]);
    let lexer = Lexer::new(pp);
    parser::parse(lexer).unwrap()
}
<|endoftext|>


<commit_before>use benching_utils::BeaconStateBencher;
use criterion::Criterion;
use criterion::{black_box, Benchmark};
use state_processing::{
    per_epoch_processing,
    per_epoch_processing::{
        calculate_active_validator_indices, calculate_attester_sets, clean_attestations,
        process_crosslinks, process_eth1_data, process_justification,
        process_rewards_and_penalities, process_validator_registry, update_active_tree_index_roots,
        update_latest_slashed_balances,
    },
};
use types::{validator_registry::get_active_validator_indices, *};

/// Run the benchmarking suite on a foundation spec with 16,384 validators.
pub fn epoch_processing_16k_validators(c: &mut Criterion) {
    let spec = ChainSpec::foundation();

    let validator_count = 16_384;

    let mut builder = BeaconStateBencher::new(validator_count, &spec);

    // Set the state to be just before an epoch transition.
    let target_slot = (spec.genesis_epoch + 4).end_slot(spec.slots_per_epoch);
    builder.teleport_to_slot(target_slot, &spec);

    // Builds all caches; benches will not contain shuffling/committee building times.
    builder.build_caches(&spec).unwrap();

    // Inserts one attestation with full participation for each committee able to include an
    // attestation in this state.
    builder.insert_attestations(&spec);

    let (state, _keypairs) = builder.build();

    // Assert that the state has an attestations for each committee that is able to include an
    // attestation in the state.
    let committees_per_epoch = spec.get_epoch_committee_count(validator_count);
    let committees_per_slot = committees_per_epoch / spec.slots_per_epoch;
    let previous_epoch_attestations = committees_per_epoch;
    let current_epoch_attestations =
        committees_per_slot * (spec.slots_per_epoch - spec.min_attestation_inclusion_delay);
    assert_eq!(
        state.latest_attestations.len() as u64,
        previous_epoch_attestations + current_epoch_attestations,
        "The state should have an attestation for each committee."
    );

    // Assert that each attestation in the state has full participation.
    let committee_size = validator_count / committees_per_epoch as usize;
    for a in &state.latest_attestations {
        assert_eq!(
            a.aggregation_bitfield.num_set_bits(),
            committee_size,
            "Each attestation in the state should have full participation"
        );
    }

    // Assert that we will run the first arm of process_rewards_and_penalities
    let epochs_since_finality = state.next_epoch(&spec) - state.finalized_epoch;
    assert_eq!(
        epochs_since_finality, 4,
        "Epochs since finality should be 4"
    );

    bench_epoch_processing(c, &state, &spec, "16k_validators");
}

/// Run the detailed benchmarking suite on the given `BeaconState`.
///
/// `desc` will be added to the title of each bench.
fn bench_epoch_processing(c: &mut Criterion, state: &BeaconState, spec: &ChainSpec, desc: &str) {
    let state_clone = state.clone();
    let spec_clone = spec.clone();
    c.bench(
        &format!("epoch_process_with_caches_{}", desc),
        Benchmark::new("full run", move |b| {
            b.iter_with_setup(
                || state_clone.clone(),
                |mut state| black_box(per_epoch_processing(&mut state, &spec_clone).unwrap()),
            )
        })
        .sample_size(10),
    );

    let state_clone = state.clone();
    let spec_clone = spec.clone();
    c.bench(
        &format!("epoch_process_with_caches_{}", desc),
        Benchmark::new("calculate_active_validator_indices", move |b| {
            b.iter_with_setup(
                || state_clone.clone(),
                |mut state| black_box(calculate_active_validator_indices(&mut state, &spec_clone)),
            )
        })
        .sample_size(10),
    );

    let state_clone = state.clone();
    let spec_clone = spec.clone();
    let active_validator_indices = calculate_active_validator_indices(&state, &spec);
    c.bench(
        &format!("epoch_process_with_caches_{}", desc),
        Benchmark::new("calculate_current_total_balance", move |b| {
            b.iter_with_setup(
                || state_clone.clone(),
                |state| {
                    black_box(state.get_total_balance(&active_validator_indices[..], &spec_clone))
                },
            )
        })
        .sample_size(10),
    );

    let state_clone = state.clone();
    let spec_clone = spec.clone();
    c.bench(
        &format!("epoch_process_with_caches_{}", desc),
        Benchmark::new("calculate_previous_total_balance", move |b| {
            b.iter_with_setup(
                || state_clone.clone(),
                |state| {
                    black_box(state.get_total_balance(
                        &get_active_validator_indices(
                            &state.validator_registry,
                            state.previous_epoch(&spec_clone),
                        )[..],
                        &spec_clone,
                    ))
                },
            )
        })
        .sample_size(10),
    );

    let state_clone = state.clone();
    let spec_clone = spec.clone();
    c.bench(
        &format!("epoch_process_with_caches_{}", desc),
        Benchmark::new("process_eth1_data", move |b| {
            b.iter_with_setup(
                || state_clone.clone(),
                |mut state| black_box(process_eth1_data(&mut state, &spec_clone)),
            )
        })
        .sample_size(10),
    );

    let state_clone = state.clone();
    let spec_clone = spec.clone();
    c.bench(
        &format!("epoch_process_with_caches_{}", desc),
        Benchmark::new("calculate_attester_sets", move |b| {
            b.iter_with_setup(
                || state_clone.clone(),
                |mut state| black_box(calculate_attester_sets(&mut state, &spec_clone).unwrap()),
            )
        })
        .sample_size(10),
    );

    let state_clone = state.clone();
    let spec_clone = spec.clone();
    let previous_epoch = state.previous_epoch(&spec);
    let attesters = calculate_attester_sets(&state, &spec).unwrap();
    let active_validator_indices = calculate_active_validator_indices(&state, &spec);
    let current_total_balance = state.get_total_balance(&active_validator_indices[..], &spec);
    let previous_total_balance = state.get_total_balance(
        &get_active_validator_indices(&state.validator_registry, previous_epoch)[..],
        &spec,
    );
    c.bench(
        &format!("epoch_process_with_caches_{}", desc),
        Benchmark::new("process_justification", move |b| {
            b.iter_with_setup(
                || state_clone.clone(),
                |mut state| {
                    black_box(process_justification(
                        &mut state,
                        current_total_balance,
                        previous_total_balance,
                        attesters.previous_epoch_boundary.balance,
                        attesters.current_epoch_boundary.balance,
                        &spec_clone,
                    ))
                },
            )
        })
        .sample_size(10),
    );

    let state_clone = state.clone();
    let spec_clone = spec.clone();
    c.bench(
        &format!("epoch_process_with_caches_{}", desc),
        Benchmark::new("process_crosslinks", move |b| {
            b.iter_with_setup(
                || state_clone.clone(),
                |mut state| black_box(process_crosslinks(&mut state, &spec_clone).unwrap()),
            )
        })
        .sample_size(10),
    );

    let mut state_clone = state.clone();
    let spec_clone = spec.clone();
    let previous_epoch = state.previous_epoch(&spec);
    let attesters = calculate_attester_sets(&state, &spec).unwrap();
    let active_validator_indices = calculate_active_validator_indices(&state, &spec);
    let previous_total_balance = state.get_total_balance(
        &get_active_validator_indices(&state.validator_registry, previous_epoch)[..],
        &spec,
    );
    let winning_root_for_shards = process_crosslinks(&mut state_clone, &spec).unwrap();
    c.bench(
        &format!("epoch_process_with_caches_{}", desc),
        Benchmark::new("process_rewards_and_penalties", move |b| {
            b.iter_with_setup(
                || state_clone.clone(),
                |mut state| {
                    black_box(
                        process_rewards_and_penalities(
                            &mut state,
                            &active_validator_indices,
                            &attesters,
                            previous_total_balance,
                            &winning_root_for_shards,
                            &spec_clone,
                        )
                        .unwrap(),
                    )
                },
            )
        })
        .sample_size(10),
    );

    let state_clone = state.clone();
    let spec_clone = spec.clone();
    c.bench(
        &format!("epoch_process_with_caches_{}", desc),
        Benchmark::new("process_ejections", move |b| {
            b.iter_with_setup(
                || state_clone.clone(),
                |mut state| black_box(state.process_ejections(&spec_clone)),
            )
        })
        .sample_size(10),
    );

    let mut state_clone = state.clone();
    let spec_clone = spec.clone();
    let previous_epoch = state.previous_epoch(&spec);
    let attesters = calculate_attester_sets(&state, &spec).unwrap();
    let active_validator_indices = calculate_active_validator_indices(&state, &spec);
    let current_total_balance = state.get_total_balance(&active_validator_indices[..], spec);
    let previous_total_balance = state.get_total_balance(
        &get_active_validator_indices(&state.validator_registry, previous_epoch)[..],
        &spec,
    );
    assert_eq!(
        state_clone.finalized_epoch, state_clone.validator_registry_update_epoch,
        "The last registry update should be at the last finalized epoch."
    );
    process_justification(
        &mut state_clone,
        current_total_balance,
        previous_total_balance,
        attesters.previous_epoch_boundary.balance,
        attesters.current_epoch_boundary.balance,
        spec,
    );
    assert!(
        state_clone.finalized_epoch > state_clone.validator_registry_update_epoch,
        "The state should have been finalized."
    );
    c.bench(
        &format!("epoch_process_with_caches_{}", desc),
        Benchmark::new("process_validator_registry", move |b| {
            b.iter_with_setup(
                || state_clone.clone(),
                |mut state| black_box(process_validator_registry(&mut state, &spec_clone)),
            )
        })
        .sample_size(10),
    );

    let state_clone = state.clone();
    let spec_clone = spec.clone();
    c.bench(
        &format!("epoch_process_with_caches_{}", desc),
        Benchmark::new("update_active_tree_index_roots", move |b| {
            b.iter_with_setup(
                || state_clone.clone(),
                |mut state| {
                    black_box(update_active_tree_index_roots(&mut state, &spec_clone).unwrap())
                },
            )
        })
        .sample_size(10),
    );

    let state_clone = state.clone();
    let spec_clone = spec.clone();
    c.bench(
        &format!("epoch_process_with_caches_{}", desc),
        Benchmark::new("update_latest_slashed_balances", move |b| {
            b.iter_with_setup(
                || state_clone.clone(),
                |mut state| black_box(update_latest_slashed_balances(&mut state, &spec_clone)),
            )
        })
        .sample_size(10),
    );

    let state_clone = state.clone();
    let spec_clone = spec.clone();
    c.bench(
        &format!("epoch_process_with_caches_{}", desc),
        Benchmark::new("clean_attestations", move |b| {
            b.iter_with_setup(
                || state_clone.clone(),
                |mut state| black_box(clean_attestations(&mut state, &spec_clone)),
            )
        })
        .sample_size(10),
    );
}
<commit_msg>Organise epoch benching file<commit_after>use benching_utils::BeaconStateBencher;
use criterion::Criterion;
use criterion::{black_box, Benchmark};
use state_processing::{
    per_epoch_processing,
    per_epoch_processing::{
        calculate_active_validator_indices, calculate_attester_sets, clean_attestations,
        process_crosslinks, process_eth1_data, process_justification,
        process_rewards_and_penalities, process_validator_registry, update_active_tree_index_roots,
        update_latest_slashed_balances,
    },
};
use types::{validator_registry::get_active_validator_indices, *};

pub const BENCHING_SAMPLE_SIZE: usize = 100;
pub const SMALL_BENCHING_SAMPLE_SIZE: usize = 10;

/// Run the benchmarking suite on a foundation spec with 16,384 validators.
pub fn epoch_processing_16k_validators(c: &mut Criterion) {
    let spec = ChainSpec::foundation();

    let validator_count = 16_384;

    let mut builder = BeaconStateBencher::new(validator_count, &spec);

    // Set the state to be just before an epoch transition.
    let target_slot = (spec.genesis_epoch + 4).end_slot(spec.slots_per_epoch);
    builder.teleport_to_slot(target_slot, &spec);

    // Builds all caches; benches will not contain shuffling/committee building times.
    builder.build_caches(&spec).unwrap();

    // Inserts one attestation with full participation for each committee able to include an
    // attestation in this state.
    builder.insert_attestations(&spec);

    let (state, _keypairs) = builder.build();

    // Assert that the state has an attestations for each committee that is able to include an
    // attestation in the state.
    let committees_per_epoch = spec.get_epoch_committee_count(validator_count);
    let committees_per_slot = committees_per_epoch / spec.slots_per_epoch;
    let previous_epoch_attestations = committees_per_epoch;
    let current_epoch_attestations =
        committees_per_slot * (spec.slots_per_epoch - spec.min_attestation_inclusion_delay);
    assert_eq!(
        state.latest_attestations.len() as u64,
        previous_epoch_attestations + current_epoch_attestations,
        "The state should have an attestation for each committee."
    );

    // Assert that each attestation in the state has full participation.
    let committee_size = validator_count / committees_per_epoch as usize;
    for a in &state.latest_attestations {
        assert_eq!(
            a.aggregation_bitfield.num_set_bits(),
            committee_size,
            "Each attestation in the state should have full participation"
        );
    }

    // Assert that we will run the first arm of process_rewards_and_penalities
    let epochs_since_finality = state.next_epoch(&spec) - state.finalized_epoch;
    assert_eq!(
        epochs_since_finality, 4,
        "Epochs since finality should be 4"
    );

    bench_epoch_processing(c, &state, &spec, "16k_validators");
}

/// Run the detailed benchmarking suite on the given `BeaconState`.
///
/// `desc` will be added to the title of each bench.
fn bench_epoch_processing(c: &mut Criterion, state: &BeaconState, spec: &ChainSpec, desc: &str) {
    let state_clone = state.clone();
    let spec_clone = spec.clone();
    c.bench(
        &format!("epoch_process_with_caches_{}", desc),
        Benchmark::new("calculate_active_validator_indices", move |b| {
            b.iter_with_setup(
                || state_clone.clone(),
                |mut state| black_box(calculate_active_validator_indices(&mut state, &spec_clone)),
            )
        })
        .sample_size(BENCHING_SAMPLE_SIZE),
    );

    let state_clone = state.clone();
    let spec_clone = spec.clone();
    let active_validator_indices = calculate_active_validator_indices(&state, &spec);
    c.bench(
        &format!("epoch_process_with_caches_{}", desc),
        Benchmark::new("calculate_current_total_balance", move |b| {
            b.iter_with_setup(
                || state_clone.clone(),
                |state| {
                    black_box(state.get_total_balance(&active_validator_indices[..], &spec_clone))
                },
            )
        })
        .sample_size(BENCHING_SAMPLE_SIZE),
    );

    let state_clone = state.clone();
    let spec_clone = spec.clone();
    c.bench(
        &format!("epoch_process_with_caches_{}", desc),
        Benchmark::new("calculate_previous_total_balance", move |b| {
            b.iter_with_setup(
                || state_clone.clone(),
                |state| {
                    black_box(state.get_total_balance(
                        &get_active_validator_indices(
                            &state.validator_registry,
                            state.previous_epoch(&spec_clone),
                        )[..],
                        &spec_clone,
                    ))
                },
            )
        })
        .sample_size(BENCHING_SAMPLE_SIZE),
    );

    let state_clone = state.clone();
    let spec_clone = spec.clone();
    c.bench(
        &format!("epoch_process_with_caches_{}", desc),
        Benchmark::new("process_eth1_data", move |b| {
            b.iter_with_setup(
                || state_clone.clone(),
                |mut state| black_box(process_eth1_data(&mut state, &spec_clone)),
            )
        })
        .sample_size(BENCHING_SAMPLE_SIZE),
    );

    let state_clone = state.clone();
    let spec_clone = spec.clone();
    c.bench(
        &format!("epoch_process_with_caches_{}", desc),
        Benchmark::new("calculate_attester_sets", move |b| {
            b.iter_with_setup(
                || state_clone.clone(),
                |mut state| black_box(calculate_attester_sets(&mut state, &spec_clone).unwrap()),
            )
        })
        .sample_size(BENCHING_SAMPLE_SIZE),
    );

    let state_clone = state.clone();
    let spec_clone = spec.clone();
    let previous_epoch = state.previous_epoch(&spec);
    let attesters = calculate_attester_sets(&state, &spec).unwrap();
    let active_validator_indices = calculate_active_validator_indices(&state, &spec);
    let current_total_balance = state.get_total_balance(&active_validator_indices[..], &spec);
    let previous_total_balance = state.get_total_balance(
        &get_active_validator_indices(&state.validator_registry, previous_epoch)[..],
        &spec,
    );
    c.bench(
        &format!("epoch_process_with_caches_{}", desc),
        Benchmark::new("process_justification", move |b| {
            b.iter_with_setup(
                || state_clone.clone(),
                |mut state| {
                    black_box(process_justification(
                        &mut state,
                        current_total_balance,
                        previous_total_balance,
                        attesters.previous_epoch_boundary.balance,
                        attesters.current_epoch_boundary.balance,
                        &spec_clone,
                    ))
                },
            )
        })
        .sample_size(10),
    );

    let state_clone = state.clone();
    let spec_clone = spec.clone();
    c.bench(
        &format!("epoch_process_with_caches_{}", desc),
        Benchmark::new("process_crosslinks", move |b| {
            b.iter_with_setup(
                || state_clone.clone(),
                |mut state| black_box(process_crosslinks(&mut state, &spec_clone).unwrap()),
            )
        })
        .sample_size(BENCHING_SAMPLE_SIZE),
    );

    let mut state_clone = state.clone();
    let spec_clone = spec.clone();
    let previous_epoch = state.previous_epoch(&spec);
    let attesters = calculate_attester_sets(&state, &spec).unwrap();
    let active_validator_indices = calculate_active_validator_indices(&state, &spec);
    let previous_total_balance = state.get_total_balance(
        &get_active_validator_indices(&state.validator_registry, previous_epoch)[..],
        &spec,
    );
    let winning_root_for_shards = process_crosslinks(&mut state_clone, &spec).unwrap();
    c.bench(
        &format!("epoch_process_with_caches_{}", desc),
        Benchmark::new("process_rewards_and_penalties", move |b| {
            b.iter_with_setup(
                || state_clone.clone(),
                |mut state| {
                    black_box(
                        process_rewards_and_penalities(
                            &mut state,
                            &active_validator_indices,
                            &attesters,
                            previous_total_balance,
                            &winning_root_for_shards,
                            &spec_clone,
                        )
                        .unwrap(),
                    )
                },
            )
        })
        .sample_size(SMALL_BENCHING_SAMPLE_SIZE),
    );

    let state_clone = state.clone();
    let spec_clone = spec.clone();
    c.bench(
        &format!("epoch_process_with_caches_{}", desc),
        Benchmark::new("process_ejections", move |b| {
            b.iter_with_setup(
                || state_clone.clone(),
                |mut state| black_box(state.process_ejections(&spec_clone)),
            )
        })
        .sample_size(BENCHING_SAMPLE_SIZE),
    );

    let mut state_clone = state.clone();
    let spec_clone = spec.clone();
    let previous_epoch = state.previous_epoch(&spec);
    let attesters = calculate_attester_sets(&state, &spec).unwrap();
    let active_validator_indices = calculate_active_validator_indices(&state, &spec);
    let current_total_balance = state.get_total_balance(&active_validator_indices[..], spec);
    let previous_total_balance = state.get_total_balance(
        &get_active_validator_indices(&state.validator_registry, previous_epoch)[..],
        &spec,
    );
    assert_eq!(
        state_clone.finalized_epoch, state_clone.validator_registry_update_epoch,
        "The last registry update should be at the last finalized epoch."
    );
    process_justification(
        &mut state_clone,
        current_total_balance,
        previous_total_balance,
        attesters.previous_epoch_boundary.balance,
        attesters.current_epoch_boundary.balance,
        spec,
    );
    assert!(
        state_clone.finalized_epoch > state_clone.validator_registry_update_epoch,
        "The state should have been finalized."
    );
    c.bench(
        &format!("epoch_process_with_caches_{}", desc),
        Benchmark::new("process_validator_registry", move |b| {
            b.iter_with_setup(
                || state_clone.clone(),
                |mut state| black_box(process_validator_registry(&mut state, &spec_clone)),
            )
        })
        .sample_size(BENCHING_SAMPLE_SIZE),
    );

    let state_clone = state.clone();
    let spec_clone = spec.clone();
    c.bench(
        &format!("epoch_process_with_caches_{}", desc),
        Benchmark::new("update_active_tree_index_roots", move |b| {
            b.iter_with_setup(
                || state_clone.clone(),
                |mut state| {
                    black_box(update_active_tree_index_roots(&mut state, &spec_clone).unwrap())
                },
            )
        })
        .sample_size(BENCHING_SAMPLE_SIZE),
    );

    let state_clone = state.clone();
    let spec_clone = spec.clone();
    c.bench(
        &format!("epoch_process_with_caches_{}", desc),
        Benchmark::new("update_latest_slashed_balances", move |b| {
            b.iter_with_setup(
                || state_clone.clone(),
                |mut state| black_box(update_latest_slashed_balances(&mut state, &spec_clone)),
            )
        })
        .sample_size(BENCHING_SAMPLE_SIZE),
    );

    let state_clone = state.clone();
    let spec_clone = spec.clone();
    c.bench(
        &format!("epoch_process_with_caches_{}", desc),
        Benchmark::new("clean_attestations", move |b| {
            b.iter_with_setup(
                || state_clone.clone(),
                |mut state| black_box(clean_attestations(&mut state, &spec_clone)),
            )
        })
        .sample_size(BENCHING_SAMPLE_SIZE),
    );

    let state_clone = state.clone();
    let spec_clone = spec.clone();
    c.bench(
        &format!("epoch_process_with_caches_{}", desc),
        Benchmark::new("per_epoch_processing", move |b| {
            b.iter_with_setup(
                || state_clone.clone(),
                |mut state| black_box(per_epoch_processing(&mut state, &spec_clone).unwrap()),
            )
        })
        .sample_size(SMALL_BENCHING_SAMPLE_SIZE),
    );
}
<|endoftext|>