<commit_before>/*
Module: generic_os

Some miscellaneous platform functions.

These should be rolled into another module.
*/

import core::option;

// Wow, this is an ugly way to write doc comments

#[cfg(bogus)]
#[doc = "Get the value of an environment variable"]
fn getenv(n: str) -> option<str> { }

#[cfg(bogus)]
#[doc = "Set the value of an environment variable"]
fn setenv(n: str, v: str) { }

fn env() -> [(str,str)] {
    let pairs = [];
    for p in os::rustrt::rust_env_pairs() {
        let vs = str::splitn_char(p, '=', 1u);
        assert vec::len(vs) == 2u;
        pairs += [(vs[0], vs[1])];
    }
    ret pairs;
}

#[cfg(target_os = "linux")]
#[cfg(target_os = "macos")]
#[cfg(target_os = "freebsd")]
fn getenv(n: str) -> option<str> unsafe {
    let s = str::as_buf(n, {|buf| os::libc::getenv(buf) });
    ret if unsafe::reinterpret_cast(s) == 0 {
            option::none::<str>
        } else {
            let s = unsafe::reinterpret_cast(s);
            option::some::<str>(str::from_cstr(s))
        };
}

#[cfg(target_os = "linux")]
#[cfg(target_os = "macos")]
#[cfg(target_os = "freebsd")]
fn setenv(n: str, v: str) {
    // FIXME (868)
    str::as_buf(
        n,
        // FIXME (868)
        {|nbuf|
            str::as_buf(
                v,
                {|vbuf|
                    os::libc::setenv(nbuf, vbuf, 1i32)})});
}

#[cfg(target_os = "win32")]
fn getenv(n: str) -> option<str> {
    let nsize = 256u;
    while true {
        let v: [u8] = [];
        vec::reserve(v, nsize);
        let res =
            str::as_buf(n,
                        {|nbuf|
                            unsafe {
                            let vbuf = vec::to_ptr(v);
                            os::kernel32::GetEnvironmentVariableA(nbuf, vbuf,
                                                                  nsize)
                        }
                        });
        if res == 0u {
            ret option::none;
        } else if res < nsize {
            unsafe {
                vec::unsafe::set_len(v, res);
            }
            ret option::some(str::from_bytes(v)); // UTF-8 or fail
        } else { nsize = res; }
    }
    fail;
}

#[cfg(target_os = "win32")]
fn setenv(n: str, v: str) {
    // FIXME (868)
    let _: () =
        str::as_buf(n, {|nbuf|
            let _: () =
                str::as_buf(v, {|vbuf|
                    os::kernel32::SetEnvironmentVariableA(nbuf, vbuf);
                });
        });
}

#[cfg(test)]
mod tests {

    #[test]
    #[ignore(reason = "fails periodically on mac")]
    fn test_setenv() {
        // NB: Each test of setenv needs to use different variable names or
        // the tests will not be threadsafe
        setenv("NAME1", "VALUE");
        assert (getenv("NAME1") == option::some("VALUE"));
    }

    #[test]
    #[ignore(reason = "fails periodically on mac")]
    fn test_setenv_overwrite() {
        setenv("NAME2", "1");
        setenv("NAME2", "2");
        assert (getenv("NAME2") == option::some("2"));
    }

    // Windows GetEnvironmentVariable requires some extra work to make sure
    // the buffer the variable is copied into is the right size
    #[test]
    #[ignore(reason = "fails periodically on mac")]
    fn test_getenv_big() {
        let s = "";
        let i = 0;
        while i < 100 { s += "aaaaaaaaaa"; i += 1; }
        setenv("test_getenv_big", s);
        log(debug, s);
        assert (getenv("test_getenv_big") == option::some(s));
    }

    #[test]
    fn test_get_exe_path() {
        let path = os::get_exe_path();
        assert option::is_some(path);
        let path = option::get(path);
        log(debug, path);

        // Hard to test this function
        if os::target_os() != "win32" {
            assert str::starts_with(path, fs::path_sep());
        } else {
            assert path[1] == ':' as u8;
        }
    }
}

// Local Variables:
// mode: rust;
// fill-column: 78;
// indent-tabs-mode: nil
// c-basic-offset: 4
// buffer-file-coding-system: utf-8-unix
// End:
<commit_msg>std: Add some env() and getenv() tests<commit_after>/*
Module: generic_os

Some miscellaneous platform functions.

These should be rolled into another module.
*/

import core::option;

// Wow, this is an ugly way to write doc comments

#[cfg(bogus)]
#[doc = "Get the value of an environment variable"]
fn getenv(n: str) -> option<str> { }

#[cfg(bogus)]
#[doc = "Set the value of an environment variable"]
fn setenv(n: str, v: str) { }

fn env() -> [(str,str)] {
    let pairs = [];
    for p in os::rustrt::rust_env_pairs() {
        let vs = str::splitn_char(p, '=', 1u);
        assert vec::len(vs) == 2u;
        pairs += [(vs[0], vs[1])];
    }
    ret pairs;
}

#[cfg(target_os = "linux")]
#[cfg(target_os = "macos")]
#[cfg(target_os = "freebsd")]
fn getenv(n: str) -> option<str> unsafe {
    let s = str::as_buf(n, {|buf| os::libc::getenv(buf) });
    ret if unsafe::reinterpret_cast(s) == 0 {
            option::none::<str>
        } else {
            let s = unsafe::reinterpret_cast(s);
            option::some::<str>(str::from_cstr(s))
        };
}

#[cfg(target_os = "linux")]
#[cfg(target_os = "macos")]
#[cfg(target_os = "freebsd")]
fn setenv(n: str, v: str) {
    // FIXME (868)
    str::as_buf(
        n,
        // FIXME (868)
        {|nbuf|
            str::as_buf(
                v,
                {|vbuf|
                    os::libc::setenv(nbuf, vbuf, 1i32)})});
}

#[cfg(target_os = "win32")]
fn getenv(n: str) -> option<str> {
    let nsize = 256u;
    while true {
        let v: [u8] = [];
        vec::reserve(v, nsize);
        let res =
            str::as_buf(n,
                        {|nbuf|
                            unsafe {
                            let vbuf = vec::to_ptr(v);
                            os::kernel32::GetEnvironmentVariableA(nbuf, vbuf,
                                                                  nsize)
                        }
                        });
        if res == 0u {
            ret option::none;
        } else if res < nsize {
            unsafe {
                vec::unsafe::set_len(v, res);
            }
            ret option::some(str::from_bytes(v)); // UTF-8 or fail
        } else { nsize = res; }
    }
    fail;
}

#[cfg(target_os = "win32")]
fn setenv(n: str, v: str) {
    // FIXME (868)
    let _: () =
        str::as_buf(n, {|nbuf|
            let _: () =
                str::as_buf(v, {|vbuf|
                    os::kernel32::SetEnvironmentVariableA(nbuf, vbuf);
                });
        });
}

#[cfg(test)]
mod tests {

    fn make_rand_name() -> str {
        import rand;
        let rng: rand::rng = rand::mk_rng();
        let n = "TEST" + rng.gen_str(10u);
        assert option::is_none(getenv(n));
        n
    }

    #[test]
    #[ignore(reason = "fails periodically on mac")]
    fn test_setenv() {
        let n = make_rand_name();
        setenv(n, "VALUE");
        assert getenv(n) == option::some("VALUE");
    }

    #[test]
    #[ignore(reason = "fails periodically on mac")]
    fn test_setenv_overwrite() {
        let n = make_rand_name();
        setenv(n, "1");
        setenv(n, "2");
        assert getenv(n) == option::some("2");
        setenv(n, "");
        assert getenv(n) == option::some("");
    }

    // Windows GetEnvironmentVariable requires some extra work to make sure
    // the buffer the variable is copied into is the right size
    #[test]
    #[ignore(reason = "fails periodically on mac")]
    fn test_getenv_big() {
        let s = "";
        let i = 0;
        while i < 100 { s += "aaaaaaaaaa"; i += 1; }
        let n = make_rand_name();
        setenv(n, s);
        log(debug, s);
        assert getenv(n) == option::some(s);
    }

    #[test]
    fn test_get_exe_path() {
        let path = os::get_exe_path();
        assert option::is_some(path);
        let path = option::get(path);
        log(debug, path);

        // Hard to test this function
        if os::target_os() != "win32" {
            assert str::starts_with(path, fs::path_sep());
        } else {
            assert path[1] == ':' as u8;
        }
    }

    #[test]
    fn test_env_getenv() {
        let e = env();
        assert vec::len(e) > 0u;
        for (n, v) in e {
            log(debug, n);
            let v2 = getenv(n);
            // MingW seems to set some funky environment variables like
            // "=C:=C:\MinGW\msys\1.0\bin" and "!::=::\" that are returned
            // from env() but not visible from getenv().
            assert option::is_none(v2) || v2 == option::some(v);
        }
    }

    #[test]
    fn test_env_setenv() {
        let n = make_rand_name();

        let e = env();
        setenv(n, "VALUE");
        assert !vec::contains(e, (n, "VALUE"));

        e = env();
        assert vec::contains(e, (n, "VALUE"));
    }
}

// Local Variables:
// mode: rust;
// fill-column: 78;
// indent-tabs-mode: nil
// c-basic-offset: 4
// buffer-file-coding-system: utf-8-unix
// End:
<|endoftext|>


<commit_before>// Copyright 2013 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 clone::Clone;
use result::{Ok, Err};
use io::net::ip::SocketAddr;
use io::{Reader, Writer, IoResult};
use rt::rtio::{RtioSocket, RtioUdpSocket, IoFactory, LocalIo};

pub struct UdpSocket {
    priv obj: ~RtioUdpSocket
}

impl UdpSocket {
    pub fn bind(addr: SocketAddr) -> IoResult<UdpSocket> {
        LocalIo::maybe_raise(|io| {
            io.udp_bind(addr).map(|s| UdpSocket { obj: s })
        })
    }

    pub fn recvfrom(&mut self, buf: &mut [u8]) -> IoResult<(uint, SocketAddr)> {
        self.obj.recvfrom(buf)
    }

    pub fn sendto(&mut self, buf: &[u8], dst: SocketAddr) -> IoResult<()> {
        self.obj.sendto(buf, dst)
    }

    pub fn connect(self, other: SocketAddr) -> UdpStream {
        UdpStream { socket: self, connectedTo: other }
    }

    pub fn socket_name(&mut self) -> IoResult<SocketAddr> {
        self.obj.socket_name()
    }
}

impl Clone for UdpSocket {
    /// Creates a new handle to this UDP socket, allowing for simultaneous reads
    /// and writes of the socket.
    ///
    /// The underlying UDP socket will not be closed until all handles to the
    /// socket have been deallocated. Two concurrent reads will not receive the
    /// same data.  Instead, the first read will receive the first packet
    /// received, and the second read will receive the second packet.
    fn clone(&self) -> UdpSocket {
        UdpSocket { obj: self.obj.clone() }
    }
}

pub struct UdpStream {
    priv socket: UdpSocket,
    priv connectedTo: SocketAddr
}

impl UdpStream {
    pub fn as_socket<T>(&mut self, f: |&mut UdpSocket| -> T) -> T {
        f(&mut self.socket)
    }

    pub fn disconnect(self) -> UdpSocket { self.socket }
}

impl Reader for UdpStream {
    fn read(&mut self, buf: &mut [u8]) -> IoResult<uint> {
        let peer = self.connectedTo;
        self.as_socket(|sock| {
            match sock.recvfrom(buf) {
                Ok((_nread, src)) if src != peer => Ok(0),
                Ok((nread, _src)) => Ok(nread),
                Err(e) => Err(e),
            }
        })
    }
}

impl Writer for UdpStream {
    fn write(&mut self, buf: &[u8]) -> IoResult<()> {
        self.as_socket(|sock| sock.sendto(buf, self.connectedTo))
    }
}

#[cfg(test)]
mod test {
    use super::*;
    use io::net::ip::{SocketAddr};

    // FIXME #11530 this fails on android because tests are run as root
    iotest!(fn bind_error() {
        let addr = SocketAddr { ip: Ipv4Addr(0, 0, 0, 0), port: 1 };
        match UdpSocket::bind(addr) {
            Ok(..) => fail!(),
            Err(e) => assert_eq!(e.kind, PermissionDenied),
        }
    } #[ignore(cfg(windows))] #[ignore(cfg(target_os = "android"))])

    iotest!(fn socket_smoke_test_ip4() {
        let server_ip = next_test_ip4();
        let client_ip = next_test_ip4();
        let (port, chan) = Chan::new();
        let (port2, chan2) = Chan::new();

        spawn(proc() {
            match UdpSocket::bind(client_ip) {
                Ok(ref mut client) => {
                    port.recv();
                    client.sendto([99], server_ip).unwrap()
                }
                Err(..) => fail!()
            }
            chan2.send(());
        });

        match UdpSocket::bind(server_ip) {
            Ok(ref mut server) => {
                chan.send(());
                let mut buf = [0];
                match server.recvfrom(buf) {
                    Ok((nread, src)) => {
                        assert_eq!(nread, 1);
                        assert_eq!(buf[0], 99);
                        assert_eq!(src, client_ip);
                    }
                    Err(..) => fail!()
                }
            }
            Err(..) => fail!()
        }
        port2.recv();
    })

    iotest!(fn socket_smoke_test_ip6() {
        let server_ip = next_test_ip6();
        let client_ip = next_test_ip6();
        let (port, chan) = Chan::<()>::new();

        spawn(proc() {
            match UdpSocket::bind(client_ip) {
                Ok(ref mut client) => {
                    port.recv();
                    client.sendto([99], server_ip).unwrap()
                }
                Err(..) => fail!()
            }
        });

        match UdpSocket::bind(server_ip) {
            Ok(ref mut server) => {
                chan.send(());
                let mut buf = [0];
                match server.recvfrom(buf) {
                    Ok((nread, src)) => {
                        assert_eq!(nread, 1);
                        assert_eq!(buf[0], 99);
                        assert_eq!(src, client_ip);
                    }
                    Err(..) => fail!()
                }
            }
            Err(..) => fail!()
        }
    })

    iotest!(fn stream_smoke_test_ip4() {
        let server_ip = next_test_ip4();
        let client_ip = next_test_ip4();
        let (port, chan) = Chan::new();
        let (port2, chan2) = Chan::new();

        spawn(proc() {
            match UdpSocket::bind(client_ip) {
                Ok(client) => {
                    let client = ~client;
                    let mut stream = client.connect(server_ip);
                    port.recv();
                    stream.write([99]).unwrap();
                }
                Err(..) => fail!()
            }
            chan2.send(());
        });

        match UdpSocket::bind(server_ip) {
            Ok(server) => {
                let server = ~server;
                let mut stream = server.connect(client_ip);
                chan.send(());
                let mut buf = [0];
                match stream.read(buf) {
                    Ok(nread) => {
                        assert_eq!(nread, 1);
                        assert_eq!(buf[0], 99);
                    }
                    Err(..) => fail!()
                }
            }
            Err(..) => fail!()
        }
        port2.recv();
    })

    iotest!(fn stream_smoke_test_ip6() {
        let server_ip = next_test_ip6();
        let client_ip = next_test_ip6();
        let (port, chan) = Chan::new();
        let (port2, chan2) = Chan::new();

        spawn(proc() {
            match UdpSocket::bind(client_ip) {
                Ok(client) => {
                    let client = ~client;
                    let mut stream = client.connect(server_ip);
                    port.recv();
                    stream.write([99]).unwrap();
                }
                Err(..) => fail!()
            }
            chan2.send(());
        });

        match UdpSocket::bind(server_ip) {
            Ok(server) => {
                let server = ~server;
                let mut stream = server.connect(client_ip);
                chan.send(());
                let mut buf = [0];
                match stream.read(buf) {
                    Ok(nread) => {
                        assert_eq!(nread, 1);
                        assert_eq!(buf[0], 99);
                    }
                    Err(..) => fail!()
                }
            }
            Err(..) => fail!()
        }
        port2.recv();
    })

    pub fn socket_name(addr: SocketAddr) {
        let server = UdpSocket::bind(addr);

        assert!(server.is_ok());
        let mut server = server.unwrap();

        // Make sure socket_name gives
        // us the socket we binded to.
        let so_name = server.socket_name();
        assert!(so_name.is_ok());
        assert_eq!(addr, so_name.unwrap());
    }

    iotest!(fn socket_name_ip4() {
        socket_name(next_test_ip4());
    })

    iotest!(fn socket_name_ip6() {
        socket_name(next_test_ip6());
    })

    iotest!(fn udp_clone_smoke() {
        let addr1 = next_test_ip4();
        let addr2 = next_test_ip4();
        let mut sock1 = UdpSocket::bind(addr1).unwrap();
        let sock2 = UdpSocket::bind(addr2).unwrap();

        spawn(proc() {
            let mut sock2 = sock2;
            let mut buf = [0, 0];
            assert_eq!(sock2.recvfrom(buf), Ok((1, addr1)));
            assert_eq!(buf[0], 1);
            sock2.sendto([2], addr1).unwrap();
        });

        let sock3 = sock1.clone();

        let (p1, c1) = Chan::new();
        let (p2, c2) = Chan::new();
        spawn(proc() {
            let mut sock3 = sock3;
            p1.recv();
            sock3.sendto([1], addr2).unwrap();
            c2.send(());
        });
        c1.send(());
        let mut buf = [0, 0];
        assert_eq!(sock1.recvfrom(buf), Ok((1, addr2)));
        p2.recv();
    })

    iotest!(fn udp_clone_two_read() {
        let addr1 = next_test_ip4();
        let addr2 = next_test_ip4();
        let mut sock1 = UdpSocket::bind(addr1).unwrap();
        let sock2 = UdpSocket::bind(addr2).unwrap();
        let (p, c) = SharedChan::new();
        let c2 = c.clone();

        spawn(proc() {
            let mut sock2 = sock2;
            sock2.sendto([1], addr1).unwrap();
            p.recv();
            sock2.sendto([2], addr1).unwrap();
            p.recv();
        });

        let sock3 = sock1.clone();

        let (p, done) = Chan::new();
        spawn(proc() {
            let mut sock3 = sock3;
            let mut buf = [0, 0];
            sock3.recvfrom(buf).unwrap();
            c2.send(());
            done.send(());
        });
        let mut buf = [0, 0];
        sock1.recvfrom(buf).unwrap();
        c.send(());

        p.recv();
    })

    iotest!(fn udp_clone_two_write() {
        let addr1 = next_test_ip4();
        let addr2 = next_test_ip4();
        let mut sock1 = UdpSocket::bind(addr1).unwrap();
        let sock2 = UdpSocket::bind(addr2).unwrap();

        let (p, c) = SharedChan::new();

        spawn(proc() {
            let mut sock2 = sock2;
            let mut buf = [0, 1];

            for _ in p.iter() {
                match sock2.recvfrom(buf) {
                    Ok(..) => {}
                    Err(e) => fail!("failed receive: {}", e),
                }
            }
        });

        let sock3 = sock1.clone();

        let (p, done) = Chan::new();
        let c2 = c.clone();
        spawn(proc() {
            let mut sock3 = sock3;
            match sock3.sendto([1], addr2) {
                Ok(..) => c2.send(()),
                Err(..) => {}
            }
            done.send(());
        });
        match sock1.sendto([2], addr2) {
            Ok(..) => c.send(()),
            Err(..) => {}
        }

        p.recv();
    })
}
<commit_msg>Make a double-write UDP test more robust<commit_after>// Copyright 2013 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 clone::Clone;
use result::{Ok, Err};
use io::net::ip::SocketAddr;
use io::{Reader, Writer, IoResult};
use rt::rtio::{RtioSocket, RtioUdpSocket, IoFactory, LocalIo};

pub struct UdpSocket {
    priv obj: ~RtioUdpSocket
}

impl UdpSocket {
    pub fn bind(addr: SocketAddr) -> IoResult<UdpSocket> {
        LocalIo::maybe_raise(|io| {
            io.udp_bind(addr).map(|s| UdpSocket { obj: s })
        })
    }

    pub fn recvfrom(&mut self, buf: &mut [u8]) -> IoResult<(uint, SocketAddr)> {
        self.obj.recvfrom(buf)
    }

    pub fn sendto(&mut self, buf: &[u8], dst: SocketAddr) -> IoResult<()> {
        self.obj.sendto(buf, dst)
    }

    pub fn connect(self, other: SocketAddr) -> UdpStream {
        UdpStream { socket: self, connectedTo: other }
    }

    pub fn socket_name(&mut self) -> IoResult<SocketAddr> {
        self.obj.socket_name()
    }
}

impl Clone for UdpSocket {
    /// Creates a new handle to this UDP socket, allowing for simultaneous reads
    /// and writes of the socket.
    ///
    /// The underlying UDP socket will not be closed until all handles to the
    /// socket have been deallocated. Two concurrent reads will not receive the
    /// same data.  Instead, the first read will receive the first packet
    /// received, and the second read will receive the second packet.
    fn clone(&self) -> UdpSocket {
        UdpSocket { obj: self.obj.clone() }
    }
}

pub struct UdpStream {
    priv socket: UdpSocket,
    priv connectedTo: SocketAddr
}

impl UdpStream {
    pub fn as_socket<T>(&mut self, f: |&mut UdpSocket| -> T) -> T {
        f(&mut self.socket)
    }

    pub fn disconnect(self) -> UdpSocket { self.socket }
}

impl Reader for UdpStream {
    fn read(&mut self, buf: &mut [u8]) -> IoResult<uint> {
        let peer = self.connectedTo;
        self.as_socket(|sock| {
            match sock.recvfrom(buf) {
                Ok((_nread, src)) if src != peer => Ok(0),
                Ok((nread, _src)) => Ok(nread),
                Err(e) => Err(e),
            }
        })
    }
}

impl Writer for UdpStream {
    fn write(&mut self, buf: &[u8]) -> IoResult<()> {
        self.as_socket(|sock| sock.sendto(buf, self.connectedTo))
    }
}

#[cfg(test)]
mod test {
    use super::*;
    use io::net::ip::{SocketAddr};

    // FIXME #11530 this fails on android because tests are run as root
    iotest!(fn bind_error() {
        let addr = SocketAddr { ip: Ipv4Addr(0, 0, 0, 0), port: 1 };
        match UdpSocket::bind(addr) {
            Ok(..) => fail!(),
            Err(e) => assert_eq!(e.kind, PermissionDenied),
        }
    } #[ignore(cfg(windows))] #[ignore(cfg(target_os = "android"))])

    iotest!(fn socket_smoke_test_ip4() {
        let server_ip = next_test_ip4();
        let client_ip = next_test_ip4();
        let (port, chan) = Chan::new();
        let (port2, chan2) = Chan::new();

        spawn(proc() {
            match UdpSocket::bind(client_ip) {
                Ok(ref mut client) => {
                    port.recv();
                    client.sendto([99], server_ip).unwrap()
                }
                Err(..) => fail!()
            }
            chan2.send(());
        });

        match UdpSocket::bind(server_ip) {
            Ok(ref mut server) => {
                chan.send(());
                let mut buf = [0];
                match server.recvfrom(buf) {
                    Ok((nread, src)) => {
                        assert_eq!(nread, 1);
                        assert_eq!(buf[0], 99);
                        assert_eq!(src, client_ip);
                    }
                    Err(..) => fail!()
                }
            }
            Err(..) => fail!()
        }
        port2.recv();
    })

    iotest!(fn socket_smoke_test_ip6() {
        let server_ip = next_test_ip6();
        let client_ip = next_test_ip6();
        let (port, chan) = Chan::<()>::new();

        spawn(proc() {
            match UdpSocket::bind(client_ip) {
                Ok(ref mut client) => {
                    port.recv();
                    client.sendto([99], server_ip).unwrap()
                }
                Err(..) => fail!()
            }
        });

        match UdpSocket::bind(server_ip) {
            Ok(ref mut server) => {
                chan.send(());
                let mut buf = [0];
                match server.recvfrom(buf) {
                    Ok((nread, src)) => {
                        assert_eq!(nread, 1);
                        assert_eq!(buf[0], 99);
                        assert_eq!(src, client_ip);
                    }
                    Err(..) => fail!()
                }
            }
            Err(..) => fail!()
        }
    })

    iotest!(fn stream_smoke_test_ip4() {
        let server_ip = next_test_ip4();
        let client_ip = next_test_ip4();
        let (port, chan) = Chan::new();
        let (port2, chan2) = Chan::new();

        spawn(proc() {
            match UdpSocket::bind(client_ip) {
                Ok(client) => {
                    let client = ~client;
                    let mut stream = client.connect(server_ip);
                    port.recv();
                    stream.write([99]).unwrap();
                }
                Err(..) => fail!()
            }
            chan2.send(());
        });

        match UdpSocket::bind(server_ip) {
            Ok(server) => {
                let server = ~server;
                let mut stream = server.connect(client_ip);
                chan.send(());
                let mut buf = [0];
                match stream.read(buf) {
                    Ok(nread) => {
                        assert_eq!(nread, 1);
                        assert_eq!(buf[0], 99);
                    }
                    Err(..) => fail!()
                }
            }
            Err(..) => fail!()
        }
        port2.recv();
    })

    iotest!(fn stream_smoke_test_ip6() {
        let server_ip = next_test_ip6();
        let client_ip = next_test_ip6();
        let (port, chan) = Chan::new();
        let (port2, chan2) = Chan::new();

        spawn(proc() {
            match UdpSocket::bind(client_ip) {
                Ok(client) => {
                    let client = ~client;
                    let mut stream = client.connect(server_ip);
                    port.recv();
                    stream.write([99]).unwrap();
                }
                Err(..) => fail!()
            }
            chan2.send(());
        });

        match UdpSocket::bind(server_ip) {
            Ok(server) => {
                let server = ~server;
                let mut stream = server.connect(client_ip);
                chan.send(());
                let mut buf = [0];
                match stream.read(buf) {
                    Ok(nread) => {
                        assert_eq!(nread, 1);
                        assert_eq!(buf[0], 99);
                    }
                    Err(..) => fail!()
                }
            }
            Err(..) => fail!()
        }
        port2.recv();
    })

    pub fn socket_name(addr: SocketAddr) {
        let server = UdpSocket::bind(addr);

        assert!(server.is_ok());
        let mut server = server.unwrap();

        // Make sure socket_name gives
        // us the socket we binded to.
        let so_name = server.socket_name();
        assert!(so_name.is_ok());
        assert_eq!(addr, so_name.unwrap());
    }

    iotest!(fn socket_name_ip4() {
        socket_name(next_test_ip4());
    })

    iotest!(fn socket_name_ip6() {
        socket_name(next_test_ip6());
    })

    iotest!(fn udp_clone_smoke() {
        let addr1 = next_test_ip4();
        let addr2 = next_test_ip4();
        let mut sock1 = UdpSocket::bind(addr1).unwrap();
        let sock2 = UdpSocket::bind(addr2).unwrap();

        spawn(proc() {
            let mut sock2 = sock2;
            let mut buf = [0, 0];
            assert_eq!(sock2.recvfrom(buf), Ok((1, addr1)));
            assert_eq!(buf[0], 1);
            sock2.sendto([2], addr1).unwrap();
        });

        let sock3 = sock1.clone();

        let (p1, c1) = Chan::new();
        let (p2, c2) = Chan::new();
        spawn(proc() {
            let mut sock3 = sock3;
            p1.recv();
            sock3.sendto([1], addr2).unwrap();
            c2.send(());
        });
        c1.send(());
        let mut buf = [0, 0];
        assert_eq!(sock1.recvfrom(buf), Ok((1, addr2)));
        p2.recv();
    })

    iotest!(fn udp_clone_two_read() {
        let addr1 = next_test_ip4();
        let addr2 = next_test_ip4();
        let mut sock1 = UdpSocket::bind(addr1).unwrap();
        let sock2 = UdpSocket::bind(addr2).unwrap();
        let (p, c) = SharedChan::new();
        let c2 = c.clone();

        spawn(proc() {
            let mut sock2 = sock2;
            sock2.sendto([1], addr1).unwrap();
            p.recv();
            sock2.sendto([2], addr1).unwrap();
            p.recv();
        });

        let sock3 = sock1.clone();

        let (p, done) = Chan::new();
        spawn(proc() {
            let mut sock3 = sock3;
            let mut buf = [0, 0];
            sock3.recvfrom(buf).unwrap();
            c2.send(());
            done.send(());
        });
        let mut buf = [0, 0];
        sock1.recvfrom(buf).unwrap();
        c.send(());

        p.recv();
    })

    iotest!(fn udp_clone_two_write() {
        let addr1 = next_test_ip4();
        let addr2 = next_test_ip4();
        let mut sock1 = UdpSocket::bind(addr1).unwrap();
        let sock2 = UdpSocket::bind(addr2).unwrap();

        let (p, c) = SharedChan::new();
        let (serv_port, serv_chan) = Chan::new();

        spawn(proc() {
            let mut sock2 = sock2;
            let mut buf = [0, 1];

            p.recv();
            match sock2.recvfrom(buf) {
                Ok(..) => {}
                Err(e) => fail!("failed receive: {}", e),
            }
            serv_chan.send(());
        });

        let sock3 = sock1.clone();

        let (p, done) = Chan::new();
        let c2 = c.clone();
        spawn(proc() {
            let mut sock3 = sock3;
            match sock3.sendto([1], addr2) {
                Ok(..) => { let _ = c2.try_send(()); }
                Err(..) => {}
            }
            done.send(());
        });
        match sock1.sendto([2], addr2) {
            Ok(..) => { let _ = c.try_send(()); }
            Err(..) => {}
        }
        drop(c);

        p.recv();
        serv_port.recv();
    })
}
<|endoftext|>


<commit_before>// Copyright 2016 The Grin Developers
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

//! All the rules required for a cryptocurrency to have reach consensus across
//! the whole network are complex and hard to completely isolate. Some can be
//! simple parameters (like block reward), others complex algorithms (like
//! Merkle sum trees or reorg rules). However, as long as they're simple
//! enough, consensus-relevant constants and short functions should be kept
//! here.

use std::fmt;

use ser;
use core::target::Difficulty;

/// The block subsidy amount
pub const REWARD: u64 = 1_000_000_000;

/// Actual block reward for a given total fee amount
pub fn reward(fee: u64) -> u64 {
	REWARD + fee / 2
}

/// Number of blocks before a coinbase matures and can be spent
pub const COINBASE_MATURITY: u64 = 1_000;

/// Block interval, in seconds, the network will tune its next_target for. Note
/// that we may reduce this value in the future as we get more data on mining
/// with Cuckoo Cycle, networks improve and block propagation is optimized
/// (adjusting the reward accordingly).
pub const BLOCK_TIME_SEC: u64 = 60;

/// Cuckoo-cycle proof size (cycle length)
pub const PROOFSIZE: usize = 42;

/// Default Cuckoo Cycle size shift used for mining and validating.
pub const DEFAULT_SIZESHIFT: u8 = 30;

/// Default Cuckoo Cycle easiness, high enough to have good likeliness to find
/// a solution.
pub const EASINESS: u32 = 50;

/// Default number of blocks in the past when cross-block cut-through will start
/// happening. Needs to be long enough to not overlap with a long reorg.
/// Rational
/// behind the value is the longest bitcoin fork was about 30 blocks, so 5h. We
/// add an order of magnitude to be safe and round to 48h of blocks to make it
/// easier to reason about.
pub const CUT_THROUGH_HORIZON: u32 = 48 * 3600 / (BLOCK_TIME_SEC as u32);

/// The maximum size we're willing to accept for any message. Enforced by the
/// peer-to-peer networking layer only for DoS protection.
pub const MAX_MSG_LEN: u64 = 20_000_000;

/// Weight of an input when counted against the max block weigth capacity
pub const BLOCK_INPUT_WEIGHT: usize = 1;

/// Weight of an output when counted against the max block weight capacity
pub const BLOCK_OUTPUT_WEIGHT: usize = 10;

/// Weight of a kernel when counted against the max block weight capacity
pub const BLOCK_KERNEL_WEIGHT: usize = 2;

/// Total maximum block weight
pub const MAX_BLOCK_WEIGHT: usize = 80_000;

/// Whether a block exceeds the maximum acceptable weight
pub fn exceeds_weight(input_len: usize, output_len: usize, kernel_len: usize) -> bool {
	input_len * BLOCK_INPUT_WEIGHT + output_len * BLOCK_OUTPUT_WEIGHT +
		kernel_len * BLOCK_KERNEL_WEIGHT > MAX_BLOCK_WEIGHT
}

/// Fork every 250,000 blocks for first 2 years, simple number and just a
/// little less than 6 months.
pub const HARD_FORK_INTERVAL: u64 = 250_000;

/// Check whether the block version is valid at a given height, implements
/// 6 months interval scheduled hard forks for the first 2 years.
pub fn valid_header_version(height: u64, version: u16) -> bool {
	// uncomment below as we go from hard fork to hard fork
	if height <= HARD_FORK_INTERVAL && version == 1 {
		true
	/* } else if height <= 2 * HARD_FORK_INTERVAL && version == 2 {
		true */
	/* } else if height <= 3 * HARD_FORK_INTERVAL && version == 3 {
		true */
	/* } else if height <= 4 * HARD_FORK_INTERVAL && version == 4 {
		true */
	/* } else if height > 4 * HARD_FORK_INTERVAL && version > 4 {
		true */
	} else {
		false
	}
}

/// The minimum mining difficulty we'll allow
pub const MINIMUM_DIFFICULTY: u64 = 10;

/// Time window in blocks to calculate block time median
pub const MEDIAN_TIME_WINDOW: u64 = 11;

/// Number of blocks used to calculate difficulty adjustments
pub const DIFFICULTY_ADJUST_WINDOW: u64 = 23;

/// Average time span of the difficulty adjustment window
pub const BLOCK_TIME_WINDOW: u64 = DIFFICULTY_ADJUST_WINDOW * BLOCK_TIME_SEC;

/// Maximum size time window used for difficutly adjustments
pub const UPPER_TIME_BOUND: u64 = BLOCK_TIME_WINDOW * 4 / 3;

/// Minimum size time window used for difficutly adjustments
pub const LOWER_TIME_BOUND: u64 = BLOCK_TIME_WINDOW * 5 / 6;

/// Error when computing the next difficulty adjustment.
#[derive(Debug, Clone)]
pub struct TargetError(pub String);

impl fmt::Display for TargetError {
	fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
		write!(f, "Error computing new difficulty: {}", self.0)
	}
}

/// Computes the proof-of-work difficulty that the next block should comply
/// with. Takes an iterator over past blocks, from latest (highest height) to
/// oldest (lowest height). The iterator produces pairs of timestamp and
/// difficulty for each block.
///
/// The difficulty calculation is based on both Digishield and GravityWave
/// family of difficulty computation, coming to something very close to Zcash.
/// The refence difficulty is an average of the difficulty over a window of
/// 23 blocks. The corresponding timespan is calculated by using the
/// difference between the median timestamps at the beginning and the end
/// of the window.
pub fn next_difficulty<T>(cursor: T) -> Result<Difficulty, TargetError>
where
	T: IntoIterator<Item = Result<(u64, Difficulty), TargetError>>,
{

	// Block times at the begining and end of the adjustment window, used to
	// calculate medians later.
	let mut window_begin = vec![];
	let mut window_end = vec![];

	// Sum of difficulties in the window, used to calculate the average later.
	let mut diff_sum = Difficulty::zero();

	// Enumerating backward over blocks
	for (n, head_info) in cursor.into_iter().enumerate() {
		let m = n as u64;
		let (ts, diff) = head_info?;

		// Sum each element in the adjustment window. In addition, retain
		// timestamps within median windows (at ]start;start-11] and ]end;end-11]
		// to later calculate medians.
		if m < DIFFICULTY_ADJUST_WINDOW {
			diff_sum = diff_sum + diff;

			if m < MEDIAN_TIME_WINDOW {
				window_begin.push(ts);
			}
		} else if m < DIFFICULTY_ADJUST_WINDOW + MEDIAN_TIME_WINDOW {
			window_end.push(ts);
		} else {
			break;
		}
	}

	// Check we have enough blocks
	if window_end.len() < (MEDIAN_TIME_WINDOW as usize) {
		return Ok(Difficulty::from_num(MINIMUM_DIFFICULTY));
	}

	// Calculating time medians at the beginning and end of the window.
	window_begin.sort();
	window_end.sort();
	let begin_ts = window_begin[window_begin.len() / 2];
	let end_ts = window_end[window_end.len() / 2];

	// Average difficulty and dampened average time
	let diff_avg = diff_sum.clone() / Difficulty::from_num(DIFFICULTY_ADJUST_WINDOW);
	let ts_damp = (3 * BLOCK_TIME_WINDOW + (begin_ts - end_ts)) / 4;

	// Apply time bounds
	let adj_ts = if ts_damp < LOWER_TIME_BOUND {
		LOWER_TIME_BOUND
	} else if ts_damp > UPPER_TIME_BOUND {
		UPPER_TIME_BOUND
	} else {
		ts_damp
	};

	Ok(
		diff_avg * Difficulty::from_num(BLOCK_TIME_WINDOW) / Difficulty::from_num(adj_ts),
	)
}

/// Consensus rule that collections of items are sorted lexicographically over the wire.
pub trait VerifySortOrder<T> {
	/// Verify a collection of items is sorted as required.
	fn verify_sort_order(&self) -> Result<(), ser::Error>;
}

#[cfg(test)]
use std;

#[cfg(test)]
mod test {
	use core::target::Difficulty;

	use super::*;

	// Builds an iterator for next difficulty calculation with the provided
	// constant time interval, difficulty and total length.
	fn repeat(interval: u64, diff: u64, len: u64) -> Vec<Result<(u64, Difficulty), TargetError>> {
		// watch overflow here, length shouldn't be ridiculous anyhow
		assert!(len < std::usize::MAX as u64);
		let diffs = vec![Difficulty::from_num(diff); len as usize];
		let times = (0..(len as usize)).map(|n| n * interval as usize).rev();
		let pairs = times.zip(diffs.iter());
		pairs
			.map(|(t, d)| Ok((t as u64, d.clone())))
			.collect::<Vec<_>>()
	}

	fn repeat_offs(
		from: u64,
		interval: u64,
		diff: u64,
		len: u64,
	) -> Vec<Result<(u64, Difficulty), TargetError>> {
		map_vec!(repeat(interval, diff, len), |e| match e.clone() {
			Err(e) => Err(e),
			Ok((t, d)) => Ok((t + from, d)),
		})
	}

	/// Checks different next_target adjustments and difficulty boundaries
	#[test]
	fn next_target_adjustment() {
		// not enough data
		assert_eq!(
			next_difficulty(vec![]).unwrap(),
			Difficulty::from_num(MINIMUM_DIFFICULTY)
		);

		assert_eq!(
			next_difficulty(vec![Ok((60, Difficulty::one()))]).unwrap(),
			Difficulty::from_num(MINIMUM_DIFFICULTY)
		);

		assert_eq!(
			next_difficulty(repeat(60, 10, DIFFICULTY_ADJUST_WINDOW)).unwrap(),
			Difficulty::from_num(MINIMUM_DIFFICULTY)
		);

		// just enough data, right interval, should stay constant

		let just_enough = DIFFICULTY_ADJUST_WINDOW + MEDIAN_TIME_WINDOW;
		assert_eq!(
			next_difficulty(repeat(60, 1000, just_enough)).unwrap(),
			Difficulty::from_num(1000)
		);

		// checking averaging works, window length is odd so need to compensate a little
		let sec = DIFFICULTY_ADJUST_WINDOW / 2 + 1 + MEDIAN_TIME_WINDOW;
		let mut s1 = repeat(60, 500, sec);
		let mut s2 = repeat_offs((sec * 60) as u64, 60, 1545, DIFFICULTY_ADJUST_WINDOW / 2);
		s2.append(&mut s1);
		assert_eq!(next_difficulty(s2).unwrap(), Difficulty::from_num(999));

		// too slow, diff goes down
		assert_eq!(
			next_difficulty(repeat(90, 1000, just_enough)).unwrap(),
			Difficulty::from_num(889)
		);
		assert_eq!(
			next_difficulty(repeat(120, 1000, just_enough)).unwrap(),
			Difficulty::from_num(800)
		);

		// too fast, diff goes up
		assert_eq!(
			next_difficulty(repeat(55, 1000, just_enough)).unwrap(),
			Difficulty::from_num(1021)
		);
		assert_eq!(
			next_difficulty(repeat(45, 1000, just_enough)).unwrap(),
			Difficulty::from_num(1067)
		);

		// hitting lower time bound, should always get the same result below
		assert_eq!(
			next_difficulty(repeat(20, 1000, just_enough)).unwrap(),
			Difficulty::from_num(1200)
		);
		assert_eq!(
			next_difficulty(repeat(10, 1000, just_enough)).unwrap(),
			Difficulty::from_num(1200)
		);

		// hitting higher time bound, should always get the same result above
		assert_eq!(
			next_difficulty(repeat(160, 1000, just_enough)).unwrap(),
			Difficulty::from_num(750)
		);
		assert_eq!(
			next_difficulty(repeat(200, 1000, just_enough)).unwrap(),
			Difficulty::from_num(750)
		);
	}

	#[test]
	fn hard_fork_1() {
		assert!(valid_header_version(0, 1));
		assert!(valid_header_version(10, 1));
		assert!(!valid_header_version(10, 2));
		assert!(valid_header_version(250_000, 1));
		assert!(!valid_header_version(250_001, 1));
		assert!(!valid_header_version(500_000, 1));
		assert!(!valid_header_version(250_001, 2));
	}

	// #[test]
	// fn hard_fork_2() {
	// 	assert!(valid_header_version(0, 1));
	// 	assert!(valid_header_version(10, 1));
	// 	assert!(valid_header_version(10, 2));
	// 	assert!(valid_header_version(250_000, 1));
	// 	assert!(!valid_header_version(250_001, 1));
	// 	assert!(!valid_header_version(500_000, 1));
	// 	assert!(valid_header_version(250_001, 2));
	// 	assert!(valid_header_version(500_000, 2));
	// 	assert!(!valid_header_version(500_001, 2));
	// }
}
<commit_msg>Consensus change: set reward and base grin unit<commit_after>// Copyright 2016 The Grin Developers
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

//! All the rules required for a cryptocurrency to have reach consensus across
//! the whole network are complex and hard to completely isolate. Some can be
//! simple parameters (like block reward), others complex algorithms (like
//! Merkle sum trees or reorg rules). However, as long as they're simple
//! enough, consensus-relevant constants and short functions should be kept
//! here.

use std::fmt;

use ser;
use core::target::Difficulty;

/// A grin is divisible to 10^9, a nanogrin
pub const GRIN_BASE: u64 = 1_000_000_000;

/// The block subsidy amount
pub const REWARD: u64 = 50*GRIN_BASE;

/// Actual block reward for a given total fee amount
pub fn reward(fee: u64) -> u64 {
	REWARD + fee / 2
}

/// Number of blocks before a coinbase matures and can be spent
pub const COINBASE_MATURITY: u64 = 1_000;

/// Block interval, in seconds, the network will tune its next_target for. Note
/// that we may reduce this value in the future as we get more data on mining
/// with Cuckoo Cycle, networks improve and block propagation is optimized
/// (adjusting the reward accordingly).
pub const BLOCK_TIME_SEC: u64 = 60;

/// Cuckoo-cycle proof size (cycle length)
pub const PROOFSIZE: usize = 42;

/// Default Cuckoo Cycle size shift used for mining and validating.
pub const DEFAULT_SIZESHIFT: u8 = 30;

/// Default Cuckoo Cycle easiness, high enough to have good likeliness to find
/// a solution.
pub const EASINESS: u32 = 50;

/// Default number of blocks in the past when cross-block cut-through will start
/// happening. Needs to be long enough to not overlap with a long reorg.
/// Rational
/// behind the value is the longest bitcoin fork was about 30 blocks, so 5h. We
/// add an order of magnitude to be safe and round to 48h of blocks to make it
/// easier to reason about.
pub const CUT_THROUGH_HORIZON: u32 = 48 * 3600 / (BLOCK_TIME_SEC as u32);

/// The maximum size we're willing to accept for any message. Enforced by the
/// peer-to-peer networking layer only for DoS protection.
pub const MAX_MSG_LEN: u64 = 20_000_000;

/// Weight of an input when counted against the max block weigth capacity
pub const BLOCK_INPUT_WEIGHT: usize = 1;

/// Weight of an output when counted against the max block weight capacity
pub const BLOCK_OUTPUT_WEIGHT: usize = 10;

/// Weight of a kernel when counted against the max block weight capacity
pub const BLOCK_KERNEL_WEIGHT: usize = 2;

/// Total maximum block weight
pub const MAX_BLOCK_WEIGHT: usize = 80_000;

/// Whether a block exceeds the maximum acceptable weight
pub fn exceeds_weight(input_len: usize, output_len: usize, kernel_len: usize) -> bool {
	input_len * BLOCK_INPUT_WEIGHT + output_len * BLOCK_OUTPUT_WEIGHT +
		kernel_len * BLOCK_KERNEL_WEIGHT > MAX_BLOCK_WEIGHT
}

/// Fork every 250,000 blocks for first 2 years, simple number and just a
/// little less than 6 months.
pub const HARD_FORK_INTERVAL: u64 = 250_000;

/// Check whether the block version is valid at a given height, implements
/// 6 months interval scheduled hard forks for the first 2 years.
pub fn valid_header_version(height: u64, version: u16) -> bool {
	// uncomment below as we go from hard fork to hard fork
	if height <= HARD_FORK_INTERVAL && version == 1 {
		true
	/* } else if height <= 2 * HARD_FORK_INTERVAL && version == 2 {
		true */
	/* } else if height <= 3 * HARD_FORK_INTERVAL && version == 3 {
		true */
	/* } else if height <= 4 * HARD_FORK_INTERVAL && version == 4 {
		true */
	/* } else if height > 4 * HARD_FORK_INTERVAL && version > 4 {
		true */
	} else {
		false
	}
}

/// The minimum mining difficulty we'll allow
pub const MINIMUM_DIFFICULTY: u64 = 10;

/// Time window in blocks to calculate block time median
pub const MEDIAN_TIME_WINDOW: u64 = 11;

/// Number of blocks used to calculate difficulty adjustments
pub const DIFFICULTY_ADJUST_WINDOW: u64 = 23;

/// Average time span of the difficulty adjustment window
pub const BLOCK_TIME_WINDOW: u64 = DIFFICULTY_ADJUST_WINDOW * BLOCK_TIME_SEC;

/// Maximum size time window used for difficutly adjustments
pub const UPPER_TIME_BOUND: u64 = BLOCK_TIME_WINDOW * 4 / 3;

/// Minimum size time window used for difficutly adjustments
pub const LOWER_TIME_BOUND: u64 = BLOCK_TIME_WINDOW * 5 / 6;

/// Error when computing the next difficulty adjustment.
#[derive(Debug, Clone)]
pub struct TargetError(pub String);

impl fmt::Display for TargetError {
	fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
		write!(f, "Error computing new difficulty: {}", self.0)
	}
}

/// Computes the proof-of-work difficulty that the next block should comply
/// with. Takes an iterator over past blocks, from latest (highest height) to
/// oldest (lowest height). The iterator produces pairs of timestamp and
/// difficulty for each block.
///
/// The difficulty calculation is based on both Digishield and GravityWave
/// family of difficulty computation, coming to something very close to Zcash.
/// The refence difficulty is an average of the difficulty over a window of
/// 23 blocks. The corresponding timespan is calculated by using the
/// difference between the median timestamps at the beginning and the end
/// of the window.
pub fn next_difficulty<T>(cursor: T) -> Result<Difficulty, TargetError>
where
	T: IntoIterator<Item = Result<(u64, Difficulty), TargetError>>,
{

	// Block times at the begining and end of the adjustment window, used to
	// calculate medians later.
	let mut window_begin = vec![];
	let mut window_end = vec![];

	// Sum of difficulties in the window, used to calculate the average later.
	let mut diff_sum = Difficulty::zero();

	// Enumerating backward over blocks
	for (n, head_info) in cursor.into_iter().enumerate() {
		let m = n as u64;
		let (ts, diff) = head_info?;

		// Sum each element in the adjustment window. In addition, retain
		// timestamps within median windows (at ]start;start-11] and ]end;end-11]
		// to later calculate medians.
		if m < DIFFICULTY_ADJUST_WINDOW {
			diff_sum = diff_sum + diff;

			if m < MEDIAN_TIME_WINDOW {
				window_begin.push(ts);
			}
		} else if m < DIFFICULTY_ADJUST_WINDOW + MEDIAN_TIME_WINDOW {
			window_end.push(ts);
		} else {
			break;
		}
	}

	// Check we have enough blocks
	if window_end.len() < (MEDIAN_TIME_WINDOW as usize) {
		return Ok(Difficulty::from_num(MINIMUM_DIFFICULTY));
	}

	// Calculating time medians at the beginning and end of the window.
	window_begin.sort();
	window_end.sort();
	let begin_ts = window_begin[window_begin.len() / 2];
	let end_ts = window_end[window_end.len() / 2];

	// Average difficulty and dampened average time
	let diff_avg = diff_sum.clone() / Difficulty::from_num(DIFFICULTY_ADJUST_WINDOW);
	let ts_damp = (3 * BLOCK_TIME_WINDOW + (begin_ts - end_ts)) / 4;

	// Apply time bounds
	let adj_ts = if ts_damp < LOWER_TIME_BOUND {
		LOWER_TIME_BOUND
	} else if ts_damp > UPPER_TIME_BOUND {
		UPPER_TIME_BOUND
	} else {
		ts_damp
	};

	Ok(
		diff_avg * Difficulty::from_num(BLOCK_TIME_WINDOW) / Difficulty::from_num(adj_ts),
	)
}

/// Consensus rule that collections of items are sorted lexicographically over the wire.
pub trait VerifySortOrder<T> {
	/// Verify a collection of items is sorted as required.
	fn verify_sort_order(&self) -> Result<(), ser::Error>;
}

#[cfg(test)]
use std;

#[cfg(test)]
mod test {
	use core::target::Difficulty;

	use super::*;

	// Builds an iterator for next difficulty calculation with the provided
	// constant time interval, difficulty and total length.
	fn repeat(interval: u64, diff: u64, len: u64) -> Vec<Result<(u64, Difficulty), TargetError>> {
		// watch overflow here, length shouldn't be ridiculous anyhow
		assert!(len < std::usize::MAX as u64);
		let diffs = vec![Difficulty::from_num(diff); len as usize];
		let times = (0..(len as usize)).map(|n| n * interval as usize).rev();
		let pairs = times.zip(diffs.iter());
		pairs
			.map(|(t, d)| Ok((t as u64, d.clone())))
			.collect::<Vec<_>>()
	}

	fn repeat_offs(
		from: u64,
		interval: u64,
		diff: u64,
		len: u64,
	) -> Vec<Result<(u64, Difficulty), TargetError>> {
		map_vec!(repeat(interval, diff, len), |e| match e.clone() {
			Err(e) => Err(e),
			Ok((t, d)) => Ok((t + from, d)),
		})
	}

	/// Checks different next_target adjustments and difficulty boundaries
	#[test]
	fn next_target_adjustment() {
		// not enough data
		assert_eq!(
			next_difficulty(vec![]).unwrap(),
			Difficulty::from_num(MINIMUM_DIFFICULTY)
		);

		assert_eq!(
			next_difficulty(vec![Ok((60, Difficulty::one()))]).unwrap(),
			Difficulty::from_num(MINIMUM_DIFFICULTY)
		);

		assert_eq!(
			next_difficulty(repeat(60, 10, DIFFICULTY_ADJUST_WINDOW)).unwrap(),
			Difficulty::from_num(MINIMUM_DIFFICULTY)
		);

		// just enough data, right interval, should stay constant

		let just_enough = DIFFICULTY_ADJUST_WINDOW + MEDIAN_TIME_WINDOW;
		assert_eq!(
			next_difficulty(repeat(60, 1000, just_enough)).unwrap(),
			Difficulty::from_num(1000)
		);

		// checking averaging works, window length is odd so need to compensate a little
		let sec = DIFFICULTY_ADJUST_WINDOW / 2 + 1 + MEDIAN_TIME_WINDOW;
		let mut s1 = repeat(60, 500, sec);
		let mut s2 = repeat_offs((sec * 60) as u64, 60, 1545, DIFFICULTY_ADJUST_WINDOW / 2);
		s2.append(&mut s1);
		assert_eq!(next_difficulty(s2).unwrap(), Difficulty::from_num(999));

		// too slow, diff goes down
		assert_eq!(
			next_difficulty(repeat(90, 1000, just_enough)).unwrap(),
			Difficulty::from_num(889)
		);
		assert_eq!(
			next_difficulty(repeat(120, 1000, just_enough)).unwrap(),
			Difficulty::from_num(800)
		);

		// too fast, diff goes up
		assert_eq!(
			next_difficulty(repeat(55, 1000, just_enough)).unwrap(),
			Difficulty::from_num(1021)
		);
		assert_eq!(
			next_difficulty(repeat(45, 1000, just_enough)).unwrap(),
			Difficulty::from_num(1067)
		);

		// hitting lower time bound, should always get the same result below
		assert_eq!(
			next_difficulty(repeat(20, 1000, just_enough)).unwrap(),
			Difficulty::from_num(1200)
		);
		assert_eq!(
			next_difficulty(repeat(10, 1000, just_enough)).unwrap(),
			Difficulty::from_num(1200)
		);

		// hitting higher time bound, should always get the same result above
		assert_eq!(
			next_difficulty(repeat(160, 1000, just_enough)).unwrap(),
			Difficulty::from_num(750)
		);
		assert_eq!(
			next_difficulty(repeat(200, 1000, just_enough)).unwrap(),
			Difficulty::from_num(750)
		);
	}

	#[test]
	fn hard_fork_1() {
		assert!(valid_header_version(0, 1));
		assert!(valid_header_version(10, 1));
		assert!(!valid_header_version(10, 2));
		assert!(valid_header_version(250_000, 1));
		assert!(!valid_header_version(250_001, 1));
		assert!(!valid_header_version(500_000, 1));
		assert!(!valid_header_version(250_001, 2));
	}

	// #[test]
	// fn hard_fork_2() {
	// 	assert!(valid_header_version(0, 1));
	// 	assert!(valid_header_version(10, 1));
	// 	assert!(valid_header_version(10, 2));
	// 	assert!(valid_header_version(250_000, 1));
	// 	assert!(!valid_header_version(250_001, 1));
	// 	assert!(!valid_header_version(500_000, 1));
	// 	assert!(valid_header_version(250_001, 2));
	// 	assert!(valid_header_version(500_000, 2));
	// 	assert!(!valid_header_version(500_001, 2));
	// }
}
<|endoftext|>


<commit_before>// Copyright 2016 The Grin Developers
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

//! All the rules required for a cryptocurrency to have reach consensus across
//! the whole network are complex and hard to completely isolate. Some can be
//! simple parameters (like block reward), others complex algorithms (like
//! Merkle sum trees or reorg rules). However, as long as they're simple
//! emough, consensus-relevant constants and short functions should be kept
//! here.

/// The block subsidy amount
pub const REWARD: u64 = 1_000_000_000;

/// Block interval, in seconds
pub const BLOCK_TIME_SEC: u8 = 15;

/// Cuckoo-cycle proof size (cycle length)
pub const PROOFSIZE: usize = 42;

/// Default Cuckoo Cycle size shift used is 28. We may decide to increase it.
/// when difficuty increases.
pub const SIZESHIFT: u32 = 28;

/// Default Cuckoo Cycle easiness, high enough to have good likeliness to find
/// a solution.
pub const EASINESS: u32 = 50;

/// Max target hash, lowest difficulty
pub const MAX_TARGET: [u32; PROOFSIZE] =
	[0xfff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
	 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
	 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
	 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff];

/// The maximum number of inputs or outputs a transaction may have
/// and be deserializable. Only for DoS protection.
pub const MAX_IN_OUT_LEN: u64 = 50000;
<commit_msg>A few more consensus values.<commit_after>// Copyright 2016 The Grin Developers
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

//! All the rules required for a cryptocurrency to have reach consensus across
//! the whole network are complex and hard to completely isolate. Some can be
//! simple parameters (like block reward), others complex algorithms (like
//! Merkle sum trees or reorg rules). However, as long as they're simple
//! emough, consensus-relevant constants and short functions should be kept
//! here.

/// The block subsidy amount
pub const REWARD: u64 = 1_000_000_000;

/// Block interval, in seconds, the network will tune its difficulty for. Note
/// that contrarily to bitcoin, we may reduce this value in the future as
/// networks improve and block propagation is optimized (adjusting the reward
/// accordingly).
pub const BLOCK_TIME_SEC: u8 = 30;

/// Cuckoo-cycle proof size (cycle length)
pub const PROOFSIZE: usize = 42;

/// Default Cuckoo Cycle size shift used is 28. We may decide to increase it
/// when hashrate increases. May also start lower.
pub const SIZESHIFT: u32 = 28;

/// Default Cuckoo Cycle easiness, high enough to have good likeliness to find
/// a solution.
pub const EASINESS: u32 = 50;

/// Default number of blocks in the past when cross-block cut-through will start
/// happening. Needs to be long enough to not overlap with a long reorg. Rational
/// behind the value is the longest bitcoin fork was about 30 blocks, so 5h. We
/// add an order of magnitude to be safe and round to 48h of blocks to make it
/// easier to reason about.
pub const CUT_THROUGH_HORIZON: u32 = 48 * 3600 / (BLOCK_TIME_SEC as u32);

/// Max target hash, lowest difficulty
pub const MAX_TARGET: [u32; PROOFSIZE] =
	[0xfff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
	 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
	 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
	 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff];

/// The maximum number of inputs or outputs a transaction may have
/// and be deserializable. Only for DoS protection.
pub const MAX_IN_OUT_LEN: u64 = 50000;
<|endoftext|>


<commit_before>#[macro_use]
pub mod types;

use self::types::*;
use common::combinator::Parser;
use common::util::*;
use std::iter::FromIterator;

pub fn tokenize<T: Iterator<Item = char>>(input: T) -> Result<Vec<Token>> {
    let mut l = Lexer::new(input);

    let mut result = Vec::default();

    loop {
        let _ = skip_whitespaces(&mut l);
        match l.preview() {
            None => break,
            _ => {
                result.push(try!(lex_token(&mut l)));
            }
        }
    }

    Ok(result)
}

fn skip_whitespaces(l: &mut Lexer) -> Result<Vec<char>> {
    l.many(|l| l.predicate(|x| [' ', '\t', '\n', '\r'].contains(x)))
}

fn lex_token(l: &mut Lexer) -> Result<Token> {
    l.choose(&[&lex_operator,
               &lex_punctuation,
               &lex_string,
               &lex_reserved_or_ident,
               &lex_integer,
               &lex_illegal])
}

macro_rules! parse_map {
    ($pat:expr, $tok:ident) => {
        &|l| {
            let pos = l.current_pos();
            let lit: String = try!(l.string($pat.chars()));
            Ok(token!($tok, pos.0, pos.1, lit))
        }
    }
}

fn lex_operator(l: &mut Lexer) -> Result<Token> {
    l.choose(&[parse_map!("==", Eq),
               parse_map!("=", Assign),
               parse_map!("+", Plus),
               parse_map!("-", Minus),
               parse_map!("*", Multiply),
               parse_map!("/", Divide),
               parse_map!("!=", NotEq),
               parse_map!("!", Not),
               parse_map!(">", GreaterThan),
               parse_map!("<", LessThan)])
}

fn lex_punctuation(l: &mut Lexer) -> Result<Token> {
    l.choose(&[parse_map!(":", Colon),
               parse_map!(";", SemiColon),
               parse_map!(",", Comma),
               parse_map!("(", LParen),
               parse_map!(")", RParen),
               parse_map!("{", LBrace),
               parse_map!("}", RBrace),
               parse_map!("[", LBracket),
               parse_map!("]", RBracket)])
}

fn lex_string(l: &mut Lexer) -> Result<Token> {
    let pos = l.current_pos();
    let mut result = Vec::default();

    result.push(try!(l.atom('"')));
    loop {
        let c = try!(l.next());
        result.push(c);
        match c {
            '\\' => result.push(try!(l.next())),
            '"' => break,
            _ => continue,
        }
    }

    Ok(token!(StringLiteral, pos.0, pos.1, String::from_iter(result)))
}

fn lex_reserved_or_ident(l: &mut Lexer) -> Result<Token> {
    let pos = l.current_pos();
    let fst = try!(l.predicate(is_letter)).to_string();
    let rest: String = try!(l.many(|l| l.predicate(is_letter_or_digit)));
    let name = fst + &rest;

    Ok(match name.as_ref() {
           "let" => token!(Let, pos.0, pos.1, name),
           "fn" => token!(Function, pos.0, pos.1, name),
           "if" => token!(If, pos.0, pos.1, name),
           "else" => token!(Else, pos.0, pos.1, name),
           "return" => token!(Return, pos.0, pos.1, name),
           "true" => token!(BoolLiteral, pos.0, pos.1, name),
           "false" => token!(BoolLiteral, pos.0, pos.1, name),
           _ => token!(Ident, pos.0, pos.1, name),
       })
}

fn lex_integer(l: &mut Lexer) -> Result<Token> {
    let pos = l.current_pos();
    let lit: String = try!(l.many(|l| l.predicate(is_digit)));
    Ok(token!(IntLiteral, pos.0, pos.1, lit))
}

fn lex_illegal(l: &mut Lexer) -> Result<Token> {
    let pos = l.current_pos();
    Ok(token!(Illegal, pos.0, pos.1, try!(l.next())))
}

#[cfg(test)]
mod tests {
    use super::*;

    fn lex(input: &str) -> Vec<Token> {
        tokenize(String::from(input).chars()).unwrap()
    }

    #[test]
    fn special_chars() {
        assert_eq!(&lex("=+(){},;"),
                   &vec![token!(Assign, 1, 1, '='),
                         token!(Plus, 1, 2, '+'),
                         token!(LParen, 1, 3, '('),
                         token!(RParen, 1, 4, ')'),
                         token!(LBrace, 1, 5, '{'),
                         token!(RBrace, 1, 6, '}'),
                         token!(Comma, 1, 7, ','),
                         token!(SemiColon, 1, 8, ';')]);
    }

    #[test]
    fn complex_code() {
        assert_eq!(&lex("
let five = 5;
let ten = 10;
let add = fn(x, y) {
    x + y;
};
let result = add(five, ten);
               "),
                   &vec![token!(Let, 2, 1, "let"),
                         token!(Ident, 2, 5, "five"),
                         token!(Assign, 2, 10, "="),
                         token!(IntLiteral, 2, 12, "5"),
                         token!(SemiColon, 2, 13, ";"),
                         token!(Let, 3, 1, "let"),
                         token!(Ident, 3, 5, "ten"),
                         token!(Assign, 3, 9, "="),
                         token!(IntLiteral, 3, 11, "10"),
                         token!(SemiColon, 3, 13, ";"),
                         token!(Let, 4, 1, "let"),
                         token!(Ident, 4, 5, "add"),
                         token!(Assign, 4, 9, "="),
                         token!(Function, 4, 11, "fn"),
                         token!(LParen, 4, 13, "("),
                         token!(Ident, 4, 14, "x"),
                         token!(Comma, 4, 15, ","),
                         token!(Ident, 4, 17, "y"),
                         token!(RParen, 4, 18, ")"),
                         token!(LBrace, 4, 20, "{"),
                         token!(Ident, 5, 5, "x"),
                         token!(Plus, 5, 7, "+"),
                         token!(Ident, 5, 9, "y"),
                         token!(SemiColon, 5, 10, ";"),
                         token!(RBrace, 6, 1, "}"),
                         token!(SemiColon, 6, 2, ";"),
                         token!(Let, 7, 1, "let"),
                         token!(Ident, 7, 5, "result"),
                         token!(Assign, 7, 12, "="),
                         token!(Ident, 7, 14, "add"),
                         token!(LParen, 7, 17, "("),
                         token!(Ident, 7, 18, "five"),
                         token!(Comma, 7, 22, ","),
                         token!(Ident, 7, 24, "ten"),
                         token!(RParen, 7, 27, ")"),
                         token!(SemiColon, 7, 28, ";")]);
    }

    #[test]
    fn complex_code2() {
        assert_eq!(&lex("
if (a == 10) {
  return a;
} else if (a != 20) {
  return !a;
} else if (a > 20) {
  return -30 / 40 * 50;
} else if (a < 30) {
  return true;
}
return false;
                    "),
                   &vec![token!(If, 2, 1, "if"),
                         token!(LParen, 2, 4, "("),
                         token!(Ident, 2, 5, "a"),
                         token!(Eq, 2, 7, "=="),
                         token!(IntLiteral, 2, 10, "10"),
                         token!(RParen, 2, 12, ")"),
                         token!(LBrace, 2, 14, "{"),
                         token!(Return, 3, 3, "return"),
                         token!(Ident, 3, 10, "a"),
                         token!(SemiColon, 3, 11, ";"),
                         token!(RBrace, 4, 1, "}"),
                         token!(Else, 4, 3, "else"),
                         token!(If, 4, 8, "if"),
                         token!(LParen, 4, 11, "("),
                         token!(Ident, 4, 12, "a"),
                         token!(NotEq, 4, 14, "!="),
                         token!(IntLiteral, 4, 17, "20"),
                         token!(RParen, 4, 19, ")"),
                         token!(LBrace, 4, 21, "{"),
                         token!(Return, 5, 3, "return"),
                         token!(Not, 5, 10, "!"),
                         token!(Ident, 5, 11, "a"),
                         token!(SemiColon, 5, 12, ";"),
                         token!(RBrace, 6, 1, "}"),
                         token!(Else, 6, 3, "else"),
                         token!(If, 6, 8, "if"),
                         token!(LParen, 6, 11, "("),
                         token!(Ident, 6, 12, "a"),
                         token!(GreaterThan, 6, 14, ">"),
                         token!(IntLiteral, 6, 16, "20"),
                         token!(RParen, 6, 18, ")"),
                         token!(LBrace, 6, 20, "{"),
                         token!(Return, 7, 3, "return"),
                         token!(Minus, 7, 10, "-"),
                         token!(IntLiteral, 7, 11, "30"),
                         token!(Divide, 7, 14, "/"),
                         token!(IntLiteral, 7, 16, "40"),
                         token!(Multiply, 7, 19, "*"),
                         token!(IntLiteral, 7, 21, "50"),
                         token!(SemiColon, 7, 23, ";"),
                         token!(RBrace, 8, 1, "}"),
                         token!(Else, 8, 3, "else"),
                         token!(If, 8, 8, "if"),
                         token!(LParen, 8, 11, "("),
                         token!(Ident, 8, 12, "a"),
                         token!(LessThan, 8, 14, "<"),
                         token!(IntLiteral, 8, 16, "30"),
                         token!(RParen, 8, 18, ")"),
                         token!(LBrace, 8, 20, "{"),
                         token!(Return, 9, 3, "return"),
                         token!(BoolLiteral, 9, 10, "true"),
                         token!(SemiColon, 9, 14, ";"),
                         token!(RBrace, 10, 1, "}"),
                         token!(Return, 11, 1, "return"),
                         token!(BoolLiteral, 11, 8, "false"),
                         token!(SemiColon, 11, 13, ";")]);
    }

    #[test]
    fn id_with_numbers() {
        assert_eq!(&lex("hello2 hel301oo120"),
                   &vec![token!(Ident, 1, 1, "hello2"),
                         token!(Ident, 1, 8, "hel301oo120")]);
    }

    #[test]
    fn string_literals() {
        assert_eq!(&lex("\"foobar\""),
                   &vec![token!(StringLiteral, 1, 1, "\"foobar\"")]);
        assert_eq!(&lex("\"foo bar\""),
                   &vec![token!(StringLiteral, 1, 1, "\"foo bar\"")]);
        assert_eq!(&lex("\"foo\\nbar\""),
                   &vec![token!(StringLiteral, 1, 1, "\"foo\\nbar\"")]);
        assert_eq!(&lex("\"foo\\tbar\""),
                   &vec![token!(StringLiteral, 1, 1, "\"foo\\tbar\"")]);
        assert_eq!(&lex("\"foo\\\"bar\""),
                   &vec![token!(StringLiteral, 1, 1, "\"foo\\\"bar\"")]);
    }

    #[test]
    fn array_tokens() {
        assert_eq!(&lex("[1, 2];"),
                   &vec![token!(LBracket, 1, 1, "["),
                         token!(IntLiteral, 1, 2, "1"),
                         token!(Comma, 1, 3, ","),
                         token!(IntLiteral, 1, 5, "2"),
                         token!(RBracket, 1, 6, "]"),
                         token!(SemiColon, 1, 7, ";")]);
    }

    #[test]
    fn hash_tokens() {
        assert_eq!(&lex("{\"hello\": \"world\"}"),
                   &vec![token!(LBrace, 1, 1, "{"),
                        token!(StringLiteral, 1, 2, "\"hello\""),
                        token!(Colon, 1, 9, ":"),
                        token!(StringLiteral, 1, 11, "\"world\""),
                        token!(RBrace, 1, 18, "}")]);
    }
}
<commit_msg>Fix lex_integer to use many1 instead of many<commit_after>#[macro_use]
pub mod types;

use self::types::*;
use common::combinator::Parser;
use common::util::*;
use std::iter::FromIterator;

pub fn tokenize<T: Iterator<Item = char>>(input: T) -> Result<Vec<Token>> {
    let mut l = Lexer::new(input);

    let mut result = Vec::default();

    loop {
        let _ = skip_whitespaces(&mut l);
        match l.preview() {
            None => break,
            _ => {
                result.push(try!(lex_token(&mut l)));
            }
        }
    }

    Ok(result)
}

fn skip_whitespaces(l: &mut Lexer) -> Result<Vec<char>> {
    l.many(|l| l.predicate(|x| [' ', '\t', '\n', '\r'].contains(x)))
}

fn lex_token(l: &mut Lexer) -> Result<Token> {
    l.choose(&[&lex_operator,
               &lex_punctuation,
               &lex_string,
               &lex_reserved_or_ident,
               &lex_integer,
               &lex_illegal])
}

macro_rules! parse_map {
    ($pat:expr, $tok:ident) => {
        &|l| {
            let pos = l.current_pos();
            let lit: String = try!(l.string($pat.chars()));
            Ok(token!($tok, pos.0, pos.1, lit))
        }
    }
}

fn lex_operator(l: &mut Lexer) -> Result<Token> {
    l.choose(&[parse_map!("==", Eq),
               parse_map!("=", Assign),
               parse_map!("+", Plus),
               parse_map!("-", Minus),
               parse_map!("*", Multiply),
               parse_map!("/", Divide),
               parse_map!("!=", NotEq),
               parse_map!("!", Not),
               parse_map!(">", GreaterThan),
               parse_map!("<", LessThan)])
}

fn lex_punctuation(l: &mut Lexer) -> Result<Token> {
    l.choose(&[parse_map!(":", Colon),
               parse_map!(";", SemiColon),
               parse_map!(",", Comma),
               parse_map!("(", LParen),
               parse_map!(")", RParen),
               parse_map!("{", LBrace),
               parse_map!("}", RBrace),
               parse_map!("[", LBracket),
               parse_map!("]", RBracket)])
}

fn lex_string(l: &mut Lexer) -> Result<Token> {
    let pos = l.current_pos();
    let mut result = Vec::default();

    result.push(try!(l.atom('"')));
    loop {
        let c = try!(l.next());
        result.push(c);
        match c {
            '\\' => result.push(try!(l.next())),
            '"' => break,
            _ => continue,
        }
    }

    Ok(token!(StringLiteral, pos.0, pos.1, String::from_iter(result)))
}

fn lex_reserved_or_ident(l: &mut Lexer) -> Result<Token> {
    let pos = l.current_pos();
    let fst = try!(l.predicate(is_letter)).to_string();
    let rest: String = try!(l.many(|l| l.predicate(is_letter_or_digit)));
    let name = fst + &rest;

    Ok(match name.as_ref() {
           "let" => token!(Let, pos.0, pos.1, name),
           "fn" => token!(Function, pos.0, pos.1, name),
           "if" => token!(If, pos.0, pos.1, name),
           "else" => token!(Else, pos.0, pos.1, name),
           "return" => token!(Return, pos.0, pos.1, name),
           "true" => token!(BoolLiteral, pos.0, pos.1, name),
           "false" => token!(BoolLiteral, pos.0, pos.1, name),
           _ => token!(Ident, pos.0, pos.1, name),
       })
}

fn lex_integer(l: &mut Lexer) -> Result<Token> {
    let pos = l.current_pos();
    let lit: String = try!(l.many1(|l| l.predicate(is_digit)));
    Ok(token!(IntLiteral, pos.0, pos.1, lit))
}

fn lex_illegal(l: &mut Lexer) -> Result<Token> {
    let pos = l.current_pos();
    Ok(token!(Illegal, pos.0, pos.1, try!(l.next())))
}

#[cfg(test)]
mod tests {
    use super::*;

    fn lex(input: &str) -> Vec<Token> {
        tokenize(String::from(input).chars()).unwrap()
    }

    #[test]
    fn special_chars() {
        assert_eq!(&lex("=+(){},;"),
                   &vec![token!(Assign, 1, 1, '='),
                         token!(Plus, 1, 2, '+'),
                         token!(LParen, 1, 3, '('),
                         token!(RParen, 1, 4, ')'),
                         token!(LBrace, 1, 5, '{'),
                         token!(RBrace, 1, 6, '}'),
                         token!(Comma, 1, 7, ','),
                         token!(SemiColon, 1, 8, ';')]);
    }

    #[test]
    fn complex_code() {
        assert_eq!(&lex("
let five = 5;
let ten = 10;
let add = fn(x, y) {
    x + y;
};
let result = add(five, ten);
               "),
                   &vec![token!(Let, 2, 1, "let"),
                         token!(Ident, 2, 5, "five"),
                         token!(Assign, 2, 10, "="),
                         token!(IntLiteral, 2, 12, "5"),
                         token!(SemiColon, 2, 13, ";"),
                         token!(Let, 3, 1, "let"),
                         token!(Ident, 3, 5, "ten"),
                         token!(Assign, 3, 9, "="),
                         token!(IntLiteral, 3, 11, "10"),
                         token!(SemiColon, 3, 13, ";"),
                         token!(Let, 4, 1, "let"),
                         token!(Ident, 4, 5, "add"),
                         token!(Assign, 4, 9, "="),
                         token!(Function, 4, 11, "fn"),
                         token!(LParen, 4, 13, "("),
                         token!(Ident, 4, 14, "x"),
                         token!(Comma, 4, 15, ","),
                         token!(Ident, 4, 17, "y"),
                         token!(RParen, 4, 18, ")"),
                         token!(LBrace, 4, 20, "{"),
                         token!(Ident, 5, 5, "x"),
                         token!(Plus, 5, 7, "+"),
                         token!(Ident, 5, 9, "y"),
                         token!(SemiColon, 5, 10, ";"),
                         token!(RBrace, 6, 1, "}"),
                         token!(SemiColon, 6, 2, ";"),
                         token!(Let, 7, 1, "let"),
                         token!(Ident, 7, 5, "result"),
                         token!(Assign, 7, 12, "="),
                         token!(Ident, 7, 14, "add"),
                         token!(LParen, 7, 17, "("),
                         token!(Ident, 7, 18, "five"),
                         token!(Comma, 7, 22, ","),
                         token!(Ident, 7, 24, "ten"),
                         token!(RParen, 7, 27, ")"),
                         token!(SemiColon, 7, 28, ";")]);
    }

    #[test]
    fn complex_code2() {
        assert_eq!(&lex("
if (a == 10) {
  return a;
} else if (a != 20) {
  return !a;
} else if (a > 20) {
  return -30 / 40 * 50;
} else if (a < 30) {
  return true;
}
return false;
                    "),
                   &vec![token!(If, 2, 1, "if"),
                         token!(LParen, 2, 4, "("),
                         token!(Ident, 2, 5, "a"),
                         token!(Eq, 2, 7, "=="),
                         token!(IntLiteral, 2, 10, "10"),
                         token!(RParen, 2, 12, ")"),
                         token!(LBrace, 2, 14, "{"),
                         token!(Return, 3, 3, "return"),
                         token!(Ident, 3, 10, "a"),
                         token!(SemiColon, 3, 11, ";"),
                         token!(RBrace, 4, 1, "}"),
                         token!(Else, 4, 3, "else"),
                         token!(If, 4, 8, "if"),
                         token!(LParen, 4, 11, "("),
                         token!(Ident, 4, 12, "a"),
                         token!(NotEq, 4, 14, "!="),
                         token!(IntLiteral, 4, 17, "20"),
                         token!(RParen, 4, 19, ")"),
                         token!(LBrace, 4, 21, "{"),
                         token!(Return, 5, 3, "return"),
                         token!(Not, 5, 10, "!"),
                         token!(Ident, 5, 11, "a"),
                         token!(SemiColon, 5, 12, ";"),
                         token!(RBrace, 6, 1, "}"),
                         token!(Else, 6, 3, "else"),
                         token!(If, 6, 8, "if"),
                         token!(LParen, 6, 11, "("),
                         token!(Ident, 6, 12, "a"),
                         token!(GreaterThan, 6, 14, ">"),
                         token!(IntLiteral, 6, 16, "20"),
                         token!(RParen, 6, 18, ")"),
                         token!(LBrace, 6, 20, "{"),
                         token!(Return, 7, 3, "return"),
                         token!(Minus, 7, 10, "-"),
                         token!(IntLiteral, 7, 11, "30"),
                         token!(Divide, 7, 14, "/"),
                         token!(IntLiteral, 7, 16, "40"),
                         token!(Multiply, 7, 19, "*"),
                         token!(IntLiteral, 7, 21, "50"),
                         token!(SemiColon, 7, 23, ";"),
                         token!(RBrace, 8, 1, "}"),
                         token!(Else, 8, 3, "else"),
                         token!(If, 8, 8, "if"),
                         token!(LParen, 8, 11, "("),
                         token!(Ident, 8, 12, "a"),
                         token!(LessThan, 8, 14, "<"),
                         token!(IntLiteral, 8, 16, "30"),
                         token!(RParen, 8, 18, ")"),
                         token!(LBrace, 8, 20, "{"),
                         token!(Return, 9, 3, "return"),
                         token!(BoolLiteral, 9, 10, "true"),
                         token!(SemiColon, 9, 14, ";"),
                         token!(RBrace, 10, 1, "}"),
                         token!(Return, 11, 1, "return"),
                         token!(BoolLiteral, 11, 8, "false"),
                         token!(SemiColon, 11, 13, ";")]);
    }

    #[test]
    fn id_with_numbers() {
        assert_eq!(&lex("hello2 hel301oo120"),
                   &vec![token!(Ident, 1, 1, "hello2"),
                         token!(Ident, 1, 8, "hel301oo120")]);
    }

    #[test]
    fn string_literals() {
        assert_eq!(&lex("\"foobar\""),
                   &vec![token!(StringLiteral, 1, 1, "\"foobar\"")]);
        assert_eq!(&lex("\"foo bar\""),
                   &vec![token!(StringLiteral, 1, 1, "\"foo bar\"")]);
        assert_eq!(&lex("\"foo\\nbar\""),
                   &vec![token!(StringLiteral, 1, 1, "\"foo\\nbar\"")]);
        assert_eq!(&lex("\"foo\\tbar\""),
                   &vec![token!(StringLiteral, 1, 1, "\"foo\\tbar\"")]);
        assert_eq!(&lex("\"foo\\\"bar\""),
                   &vec![token!(StringLiteral, 1, 1, "\"foo\\\"bar\"")]);
    }

    #[test]
    fn array_tokens() {
        assert_eq!(&lex("[1, 2];"),
                   &vec![token!(LBracket, 1, 1, "["),
                         token!(IntLiteral, 1, 2, "1"),
                         token!(Comma, 1, 3, ","),
                         token!(IntLiteral, 1, 5, "2"),
                         token!(RBracket, 1, 6, "]"),
                         token!(SemiColon, 1, 7, ";")]);
    }

    #[test]
    fn hash_tokens() {
        assert_eq!(&lex("{\"hello\": \"world\"}"),
                   &vec![token!(LBrace, 1, 1, "{"),
                        token!(StringLiteral, 1, 2, "\"hello\""),
                        token!(Colon, 1, 9, ":"),
                        token!(StringLiteral, 1, 11, "\"world\""),
                        token!(RBrace, 1, 18, "}")]);
    }
}
<|endoftext|>


<commit_before>// Rust Bitcoin Library
// Written in 2014 by
//   Andrew Poelstra <apoelstra@wpsoftware.net>
//
// To the extent possible under law, the author(s) have dedicated all
// copyright and related and neighboring rights to this software to
// the public domain worldwide. This software is distributed without
// any warranty.
//
// You should have received a copy of the CC0 Public Domain Dedication
// along with this software.
// If not, see <http://creativecommons.org/publicdomain/zero/1.0/>.
//

//! # Network constants
//!
//! This module provides various constants relating to the Bitcoin network
//! protocol, such as protocol versioning and magic header bytes.
//!

use network::encodable::{ConsensusDecodable, ConsensusEncodable};
use network::serialize::{SimpleEncoder, SimpleDecoder};

user_enum! {
    #[derive(Copy, PartialEq, Eq, Clone, Hash)]
    #[doc="The cryptocurrency to act on"]
    pub enum Network {
        #[doc="Classic Bitcoin"]
        Bitcoin <-> "bitcoin",
        #[doc="Bitcoin's testnet"]
        Testnet <-> "testnet",
        #[doc="Bitcoin's regtest"]
        Regtest <-> "regtest"
    }
}

/// Version of the protocol as appearing in network message headers
pub const PROTOCOL_VERSION: u32    = 70001;
/// Bitfield of services provided by this node
pub const SERVICES: u64            = 0;
/// User agent as it appears in the version message
pub const USER_AGENT: &'static str = "bitcoin-rust v0.1";

/// Return the network magic bytes, which should be encoded little-endian
/// at the start of every message
pub fn magic(network: Network) -> u32 {
    match network {
        Network::Bitcoin => 0xD9B4BEF9,
        Network::Testnet => 0x0709110B,
        Network::Regtest => 0xDAB5BFFA,
        // Note: any new entries here must be added to `consensus_decode` below
    }
}

impl<S: SimpleEncoder> ConsensusEncodable<S> for Network {
    #[inline]
    fn consensus_encode(&self, s: &mut S) -> Result<(), S::Error> {
        magic(*self).consensus_encode(s)
    }
}

impl<D: SimpleDecoder> ConsensusDecodable<D> for Network {
    #[inline]
    fn consensus_decode(d: &mut D) -> Result<Network, D::Error> {
        let magic: u32 = try!(ConsensusDecodable::consensus_decode(d));
        match magic {
            0xD9B4BEF9 => Ok(Network::Bitcoin),
            0x0709110B => Ok(Network::Testnet),
            0xDAB5BFFA => Ok(Network::Regtest),
            x => Err(d.error(format!("Unknown network (magic {:x})", x)))
        }
    }
}

#[cfg(test)]
mod tests {
  use super::Network;
  use network::serialize::{deserialize, serialize};

  #[test]
  fn serialize_test() {
    assert_eq!(serialize(&Network::Bitcoin).unwrap(), vec![0xf9, 0xbe, 0xb4, 0xd9]);
    assert_eq!(serialize(&Network::Testnet).unwrap(), vec![0x0b, 0x11, 0x09, 0x07]);
    assert_eq!(serialize(&Network::Regtest).unwrap(), vec![0xfa, 0xbf, 0xb5, 0xda]);

    assert_eq!(deserialize(&[0xf9, 0xbe, 0xb4, 0xd9]).ok(), Some(Network::Bitcoin));
    assert_eq!(deserialize(&[0x0b, 0x11, 0x09, 0x07]).ok(), Some(Network::Testnet));
    assert_eq!(deserialize(&[0xfa, 0xbf, 0xb5, 0xda]).ok(), Some(Network::Regtest));

    let bad: Result<Network, _> = deserialize("fakenet".as_bytes());
    assert!(bad.is_err());
  }

  #[test]
  fn string_test() {
      assert_eq!(Network::Bitcoin.to_string(), "bitcoin");
      assert_eq!(Network::Testnet.to_string(), "testnet");

      assert_eq!("bitcoin".parse::<Network>().unwrap(), Network::Bitcoin);
      assert_eq!("testnet".parse::<Network>().unwrap(), Network::Testnet);
      assert!("fakenet".parse::<Network>().is_err());
  }
}

<commit_msg>Add test for regtest network<commit_after>// Rust Bitcoin Library
// Written in 2014 by
//   Andrew Poelstra <apoelstra@wpsoftware.net>
//
// To the extent possible under law, the author(s) have dedicated all
// copyright and related and neighboring rights to this software to
// the public domain worldwide. This software is distributed without
// any warranty.
//
// You should have received a copy of the CC0 Public Domain Dedication
// along with this software.
// If not, see <http://creativecommons.org/publicdomain/zero/1.0/>.
//

//! # Network constants
//!
//! This module provides various constants relating to the Bitcoin network
//! protocol, such as protocol versioning and magic header bytes.
//!

use network::encodable::{ConsensusDecodable, ConsensusEncodable};
use network::serialize::{SimpleEncoder, SimpleDecoder};

user_enum! {
    #[derive(Copy, PartialEq, Eq, Clone, Hash)]
    #[doc="The cryptocurrency to act on"]
    pub enum Network {
        #[doc="Classic Bitcoin"]
        Bitcoin <-> "bitcoin",
        #[doc="Bitcoin's testnet"]
        Testnet <-> "testnet",
        #[doc="Bitcoin's regtest"]
        Regtest <-> "regtest"
    }
}

/// Version of the protocol as appearing in network message headers
pub const PROTOCOL_VERSION: u32    = 70001;
/// Bitfield of services provided by this node
pub const SERVICES: u64            = 0;
/// User agent as it appears in the version message
pub const USER_AGENT: &'static str = "bitcoin-rust v0.1";

/// Return the network magic bytes, which should be encoded little-endian
/// at the start of every message
pub fn magic(network: Network) -> u32 {
    match network {
        Network::Bitcoin => 0xD9B4BEF9,
        Network::Testnet => 0x0709110B,
        Network::Regtest => 0xDAB5BFFA,
        // Note: any new entries here must be added to `consensus_decode` below
    }
}

impl<S: SimpleEncoder> ConsensusEncodable<S> for Network {
    #[inline]
    fn consensus_encode(&self, s: &mut S) -> Result<(), S::Error> {
        magic(*self).consensus_encode(s)
    }
}

impl<D: SimpleDecoder> ConsensusDecodable<D> for Network {
    #[inline]
    fn consensus_decode(d: &mut D) -> Result<Network, D::Error> {
        let magic: u32 = try!(ConsensusDecodable::consensus_decode(d));
        match magic {
            0xD9B4BEF9 => Ok(Network::Bitcoin),
            0x0709110B => Ok(Network::Testnet),
            0xDAB5BFFA => Ok(Network::Regtest),
            x => Err(d.error(format!("Unknown network (magic {:x})", x)))
        }
    }
}

#[cfg(test)]
mod tests {
  use super::Network;
  use network::serialize::{deserialize, serialize};

  #[test]
  fn serialize_test() {
    assert_eq!(serialize(&Network::Bitcoin).unwrap(), vec![0xf9, 0xbe, 0xb4, 0xd9]);
    assert_eq!(serialize(&Network::Testnet).unwrap(), vec![0x0b, 0x11, 0x09, 0x07]);
    assert_eq!(serialize(&Network::Regtest).unwrap(), vec![0xfa, 0xbf, 0xb5, 0xda]);

    assert_eq!(deserialize(&[0xf9, 0xbe, 0xb4, 0xd9]).ok(), Some(Network::Bitcoin));
    assert_eq!(deserialize(&[0x0b, 0x11, 0x09, 0x07]).ok(), Some(Network::Testnet));
    assert_eq!(deserialize(&[0xfa, 0xbf, 0xb5, 0xda]).ok(), Some(Network::Regtest));

    let bad: Result<Network, _> = deserialize("fakenet".as_bytes());
    assert!(bad.is_err());
  }

  #[test]
  fn string_test() {
      assert_eq!(Network::Bitcoin.to_string(), "bitcoin");
      assert_eq!(Network::Testnet.to_string(), "testnet");
      assert_eq!(Network::Regtest.to_string(), "regtest");

      assert_eq!("bitcoin".parse::<Network>().unwrap(), Network::Bitcoin);
      assert_eq!("testnet".parse::<Network>().unwrap(), Network::Testnet);
      assert_eq!("regtest".parse::<Network>().unwrap(), Network::Regtest);
      assert!("fakenet".parse::<Network>().is_err());
  }
}

<|endoftext|>


<commit_before>use nn::modules::module::*;

#[derive(ModParse)]
pub struct Linear<'a> {
    delegate: Module<'a>,
    in_features: u32,
}

impl<'a> Linear<'a> {
    pub fn new() -> Linear<'a> {
        let mut t = Linear {
            delegate: Module::new(),
            in_features: 0,
        };
        t.init_module();
        t
    }
}

impl<'a> ModIntf<'a> for Linear<'a> {
    fn delegate(&mut self) -> &mut Module<'a> {
        &mut self.delegate
    }
    fn forward(&mut self) {}
}
<commit_msg>first cut at builder pattern<commit_after>use nn::modules::module::*;
use nn::parameter::Parameter;

#[derive(ModParse)]
pub struct Linear<'a> {
    delegate: Module<'a>,
    #[ignore]
    in_features: u32,
    #[ignore]
    out_features: u32,
    weight: Parameter<'a>,
    bias: Option<Parameter<'a>>
}

impl<'a> Linear<'a> {
	pub fn build(in_features: u32, out_features: u32) -> LinearArgsBuilder {
		LinearArgsBuilder::default()
			.in_features(in_features)
			.out_features(out_features)
	}
    pub fn new(args: LinearArgs) -> Linear<'a> {
        let mut t = Linear {
            delegate: Module::new(),
            in_features: args.in_features,
            out_features: args.out_features,
            weight: Parameter::default(),
            bias: None,
        };
        t.init_module();
        t
    }
}
#[builder(pattern="owned")]
#[derive(Builder)]
pub struct LinearArgs {
    in_features: u32,
    out_features: u32,
    #[builder(default="false")]
    bias: bool
}
impl LinearArgsBuilder {
	pub fn done<'a>(self) -> Linear<'a> {
		let args = self.build().unwrap();
		Linear::new(args)
	}
}

impl<'a> ModIntf<'a> for Linear<'a> {
    fn delegate(&mut self) -> &mut Module<'a> {
        &mut self.delegate
    }
    fn forward(&mut self) {}
}
<|endoftext|>