【Rust】スタックマシンでbufReaderを使ったソースファイルの読み込み

BufReader

use std::io::prelude::*;
use std::io::BufReader;
use std::fs::File;

fn main() -> std::io::Result<()> {
    let f = File::open("./src/address.rs")?;
    let mut reader = BufReader::new(f);

    let mut line = String::new();
    let len = reader.read_line(&mut line)?;
    println!("First line is {len} bytes long");
    Ok(())
}

ファイルを読み込んで1行ずつ処理の際は同じになる。

use std::{
    collections::HashMap,
    io::{BufRead, BufReader},
};

#[derive(Debug, Clone, PartialEq, Eq)]
enum Value {
    Num(i32),
    Op(String),
    Sym(String),
    Block(Vec<Value>),
}

impl Value {
    fn as_num(&self) -> i32 {
        match self {
        Self::Num(val) => *val,
        _ => panic!("Value is not a number"),
        }
    }

    fn to_block(self) -> Vec<Value> {
        match self {
            Self::Block(val) => val,
            _ => panic!("Value is not a block"),
        }
    }

    fn as_sym(&self) -> &str {
        if let Self::Sym(sym) = self {
            sym
        } else {
            panic!("Value is not a symbol");
        }
    }

    fn to_string(&self) -> String {
        match self {
            Self::Num(i) => i.to_string(),
            Self::Op(ref s) | Self::Sym(ref s) => s.clone(),
            Self::Block(_) => "<Block>".to_string(),
        }
    }
}

struct Vm {
    stack: Vec<Value>,
    vars: HashMap<String, Value>,
    blocks: Vec<Vec<Value>>,
}

impl Vm {
    fn new() -> Self {
        Self {
            stack: vec![],
            vars: HashMap::new(),
            blocks: vec![],
        }
    }
}

fn main() {
  if  let Some(f) = std::env::args()
    .nth(1)
    .and_then(|f| std::fs::File::open(f).ok())
    {
        parse_batch(BufReader::new(f));
    } else {
        parse_interactive();
    }
}

fn parse_batch(source: impl BufRead) -> Vec<Value> {
    let mut vm = Vm::new();
    for line in source.lines().flatten() {
        for word in line.split(" ") {
            parse_word(word, &mut vm);
        }
    }
    vm.stack
}

fn parse_interactive() {
    let mut vm = Vm::new();
    for line in std::io::stdin().lines().flatten() {
        for word in line.split(" ") {
            parse_word(word, &mut vm);
        }
        println!("stack: {:?}", vm.stack);
    }
}

fn parse_word(word: &str, vm: &mut Vm) {
    if word.is_empty() {
        return;
    }
    if word == "{" {
        vm.blocks.push(vec![]);
    } else if word == "}" {
        let top_block =
            vm.blocks.pop().expect("Block stack underrun!");
        eval(Value::Block(top_block), vm);
    } else {
        let code = if let Ok(num) = word.parse::<i32>() {
            Value::Num(num)
        } else if word.starts_with("/") {
            Value::Sym(word[1..].to_string())
        } else {
            Value::Op(word.to_string())
        };
        eval(code, vm);
    }
}


fn eval<'src>(code: Value, vm: &mut Vm) {
    if let Some(top_block) = vm.blocks.last_mut() {
        top_block.push(code);
        return;
    }
    match code {
        Value::Op(ref op) => match op as &str {
            "+" => add(&mut vm.stack),
            "-" => sub(&mut vm.stack),
            "*" => mul(&mut vm.stack),
            "/" => div(&mut vm.stack),
            "<" => lt(&mut vm.stack),
            "if" => op_if(vm),
            "def" => op_def(vm),
            "puts" => puts(vm),
            _ => {
                let val = vm.vars.get(op).expect(&format!(
                    "{op:?} is not a defined operation"
                ));
                vm.stack.push(val.clone());
            }
        },
        _ => vm.stack.push(code.clone()),
    }
}

macro_rules! impl_op {
    {$name:ident, $op:tt} => {
        fn $name(stack: &mut Vec<Value>) {
            let rhs = stack.pop().unwrap().as_num();
            let lhs = stack.pop().unwrap().as_num();
            stack.push(Value::Num((lhs $op rhs) as i32));
        }
    }
}

impl_op!(add, +);
impl_op!(sub, -);
impl_op!(mul, *);
impl_op!(div, /);
impl_op!(lt, <);

fn op_if(vm: &mut Vm) {
    let false_branch = vm.stack.pop().unwrap().to_block();
    let true_branch = vm.stack.pop().unwrap().to_block();
    let cond = vm.stack.pop().unwrap().to_block();

    for code in cond {
        eval(code, vm);
    }

    let cond_result = vm.stack.pop().unwrap().as_num();

    if cond_result != 0 {
        for code in true_branch {
            eval(code, vm);
        }
    } else {
        for code in false_branch {
            eval(code, vm);
        }
    }
}

fn op_def(vm: &mut Vm) {
    let value = vm.stack.pop().unwrap();
    eval(value, vm);
    let value = vm.stack.pop().unwrap();
    let sym = vm.stack.pop().unwrap().as_sym().to_string();

    vm.vars.insert(sym, value);
}

fn puts(vm: &mut Vm){
    let value = vm.stack.pop().unwrap();
    println!("{}", value.to_string());
}

#[cfg(test)]
mod test {
    use super::{Value::*, *};
    use std::io::Cursor;

    fn parse(input: &str) -> Vec<Value> {
        parse_batch(Cursor::new(input))
    }

    #[test]
    fn test_group(){
        assert_eq!(
            parse("1 2 + { 3 4 }"),
            vec![Num(3), Block(vec![Num(3), Num(4)])]
        );
    }

    #[test]
    fn test_if_false(){
        assert_eq!(
            parse("{ 1 -1 + } { 100 } { -100 } if"),
            vec![Num(-100)]
        );
    }

    #[test]
    fn test_if_true() {
        assert_eq!(
            parse("{ 1 1 + } { 100 } { -100 } if"),
            vec![Num(100)]
        );
    }

    #[test]
    fn test_var() {
        assert_eq!(
            parse("/x 10 def /y 20 def x y *"),
            vec![Num(200)]
        )
    }

    #[test]
    fn test_var_if() {
        assert_eq!(
            parse("/x 10 def /y 20 def { x y < } { x } { y } if"),
            vec![Num(10)]
        );
    }

    #[test]
    fn test_multiline() {
        assert_eq!(
            parse(
                r#"
                
            /x 10 def
            /y 20 def

            { x y < }
            { x }
            { y }
            if
            "#
            ),
            vec![Num(10)]
        );
    }
}

$ cargo run — if.txt
Compiling stackmachine v0.1.0 (/home/vagrant/dev/rust/stackmachine)
Finished `dev` profile [unoptimized + debuginfo] target(s) in 0.49s
Running `target/debug/stackmachine if.txt`
10

【Rust】スタックマシンの変数

hashmapに変数名と値を入れて評価する。

use std::collections::HashMap;

#[derive(Debug, Clone, PartialEq, Eq)]
enum Value<'src> {
    Num(i32),
    Op(&'src str),
    Sym(&'src str),
    Block(Vec<Value<'src>>),
}

impl<'src> Value<'src> {
    fn as_num(&self) -> i32 {
        match self {
        Self::Num(val) => *val,
        _ => panic!("Value is not a number"),
        }
    }

    fn to_block(self) -> Vec<Value<'src>> {
        match self {
            Self::Block(val) => val,
            _ => panic!("Value is not a block"),
        }
    }

    fn as_sym(&self) -> &'src str {
        if let Self::Sym(sym) = self {
            *sym
        } else {
            panic!("Value is not a symbol");
        }
    }
}

struct Vm<'src> {
    stack: Vec<Value<'src>>,
    vars: HashMap<&'src str, Value<'src>>,
}

impl<'src> Vm<'src> {
    fn new() -> Self {
        Self {
            stack: vec![],
            vars: HashMap::new(),
        }
    }
}

fn main() {
  for line in std::io::stdin().lines().flatten() {
    parse(&line);
  }
}

fn parse<'a>(line: &'a str) -> Vec<Value> {
    let mut vm = Vm::new();
    let input: Vec<_> = line.split(" ").collect();
    let mut words = &input[..];

    while let Some((&word, mut rest)) = words.split_first(){
        if word.is_empty() {
            break;
        }
        if word == "{" {
            let value;
            (value, rest) = parse_block(rest);
            vm.stack.push(value);
        } else {
            let code = if let Ok(num) = word.parse::<i32>() {
                Value::Num(num)
            } else if word.starts_with("/") {
                Value::Sym(&word[1..])
            } else {
                Value::Op(word)
            };
            eval(code, &mut vm);
        }
        words = rest;
    }
    println!("stack: {:?}", vm.stack);
    vm.stack
}

fn eval<'src>(code: Value<'src>, vm: &mut Vm<'src>) {
    match code {
        Value::Op(op) => match op {
            "+" => add(&mut vm.stack),
            "-" => sub(&mut vm.stack),
            "*" => mul(&mut vm.stack),
            "/" => div(&mut vm.stack),
            "<" => lt(&mut vm.stack),
            "if" => op_if(vm),
            "def" => op_def(vm),
            _ => {
                let val = vm.vars.get(op).expect(&format!(
                    "{op:?} is not a defined operation"
                ));
                vm.stack.push(val.clone());
            }
        },
        _ => vm.stack.push(code.clone()),
    }
}

fn parse_block<'src, 'a>(
    input: &'a [&'src  str],
) -> (Value<'src>, &'a [&'src str]){
    let mut tokens = vec![];
    let mut words = input;

    while let Some((&word, mut rest)) = words.split_first(){
        if word.is_empty() {
            break;
        }
        if word == "{" {
            let value;
            (value, rest) = parse_block(rest);
            tokens.push(value);
        } else if word == "}" {
            return (Value::Block(tokens), rest);
        } else if let Ok(value) = word.parse::<i32>() {
            tokens.push(Value::Num(value));
        } else {
            tokens.push(Value::Op(word));
        }
        words = rest;
    }
    (Value::Block(tokens), words)
}

macro_rules! impl_op {
    {$name:ident, $op:tt} => {
        fn $name(stack: &mut Vec<Value>) {
            let rhs = stack.pop().unwrap().as_num();
            let lhs = stack.pop().unwrap().as_num();
            stack.push(Value::Num((lhs $op rhs) as i32));
        }
    }
}

impl_op!(add, +);
impl_op!(sub, -);
impl_op!(mul, *);
impl_op!(div, /);
impl_op!(lt, <);

fn op_if(vm: &mut Vm) {
    let false_branch = vm.stack.pop().unwrap().to_block();
    let true_branch = vm.stack.pop().unwrap().to_block();
    let cond = vm.stack.pop().unwrap().to_block();

    for code in cond {
        eval(code, vm);
    }

    let cond_result = vm.stack.pop().unwrap().as_num();

    if cond_result != 0 {
        for code in true_branch {
            eval(code, vm);
        }
    } else {
        for code in false_branch {
            eval(code, vm);
        }
    }
}

fn op_def(vm: &mut Vm) {
    let value = vm.stack.pop().unwrap();
    eval(value, vm);
    let value = vm.stack.pop().unwrap();
    let sym = vm.stack.pop().unwrap().as_sym();

    vm.vars.insert(sym, value);
}

#[cfg(test)]
mod test {
    use super::{parse, Value::*};

    #[test]
    fn test_group(){
        assert_eq!(
            parse("1 2 + { 3 4 }"),
            vec![Num(3), Block(vec![Num(3), Num(4)])]
        );
    }

    #[test]
    fn test_if_false(){
        assert_eq!(
            parse("{ 1 -1 + } { 100 } { -100 } if"),
            vec![Num(-100)]
        );
    }

    #[test]
    fn test_if_true() {
        assert_eq!(
            parse("{ 1 1 + } { 100 } { -100 } if"),
            vec![Num(100)]
        );
    }

    #[test]
    fn test_var() {
        assert_eq!(
            parse("/x 10 def /y 20 def x y *"),
            vec![Num(200)]
        )
    }

    #[test]
    fn test_var_if() {
        assert_eq!(
            parse("/x 10 def /y 20 def { x y < } { x } { y } if"),
            vec![Num(10)]
        );
    }
}

Finished `dev` profile [unoptimized + debuginfo] target(s) in 0.01s
Running `target/debug/stackmachine`
/a 100 def /b 200 def { a b < } { a } { 0 } if stack: [Num(100)] /a 100 def /b 200 def { b a < } { a } { 0 } if stack: [Num(0)]

【Rust】マクロの基本

マクロはコンパイラとは別に用意されたプリプロセッサにより簡単な文字列置換が行われる
“=>”の左側をマッチャーと呼び、右側に展開される。

macro_rules! foo {
    ($x:expr) => { println!("{}", $x);}
}

fn main(){
    foo!(1 + 2);
}

Running `target/debug/sample`
3

### matcherに使う指定子(disanator)
item, block, stmt, pat(パターン), expr(式), ty(型), ident(識別子), path, tt(トークン木), meta(アトリビュートの中身)

macro_rules! calc {
    ($x:expr, $y:expr, $op:tt) => { 
        println!("{}", $x $op $y);
    }
}

fn main(){
    calc!(1000, 5, /);
}

Running `target/debug/sample`
200

おおお、これは凄い

【Rust】スタックマシンのif

#[derive(Debug, Clone, PartialEq, Eq)]
enum Value<'src> {
    Num(i32),
    Op(&'src str),
    Block(Vec<Value<'src>>),
}

impl<'src> Value<'src> {
    fn as_num(&self) -> i32 {
        match self {
        Self::Num(val) => *val,
        _ => panic!("Value is not a number"),
        }
    }

    fn to_block(self) -> Vec<Value<'src>> {
        match self {
            Self::Block(val) => val,
            _ => panic!("Value is not a block"),
        }
    }
}

fn main() {
  for line in std::io::stdin().lines().flatten() {
    parse(&line);
  }
}

fn parse<'a>(line: &'a str) -> Vec<Value> {
    let mut stack = vec![];
    let input: Vec<_> = line.split(" ").collect();
    let mut words = &input[..];

    while let Some((&word, mut rest)) = words.split_first(){
        if word.is_empty() {
            break;
        }
        if word == "{" {
            let value;
            (value, rest) = parse_block(rest);
            stack.push(value);
        } else {
            let code = if let Ok(num) = word.parse::<i32>() {
                Value::Num(num)
            } else {
                Value::Op(word)
            };
            eval(code, &mut stack);
        }
        words = rest;
    }
    println!("stack: {stack:?}");
    stack
}

fn eval<'src>(code: Value<'src>, stack: &mut Vec<Value<'src>>) {
    match code {
        Value::Op(op) => match op {
            "+" => add(stack),
            "-" => sub(stack),
            "*" => mul(stack),
            "/" => div(stack),
            "if" => op_if(stack),
            _ => panic!("{op:?} could not be parsed"),
        },
        _ => stack.push(code.clone()),
    }
}

fn parse_block<'src, 'a>(
    input: &'a [&'src  str],
) -> (Value<'src>, &'a [&'src str]){
    let mut tokens = vec![];
    let mut words = input;

    while let Some((&word, mut rest)) = words.split_first(){
        if word.is_empty() {
            break;
        }
        if word == "{" {
            let value;
            (value, rest) = parse_block(rest);
            tokens.push(value);
        } else if word == "}" {
            return (Value::Block(tokens), rest);
        } else if let Ok(value) = word.parse::<i32>() {
            tokens.push(Value::Num(value));
        } else {
            tokens.push(Value::Op(word));
        }
        words = rest;
    }
    (Value::Block(tokens), words)
}

fn add(stack: &mut Vec<Value>){
    let rhs = stack.pop().unwrap().as_num();
    let lhs = stack.pop().unwrap().as_num();
    stack.push(Value::Num(lhs + rhs));
}

fn sub(stack: &mut Vec<Value>){
    let rhs = stack.pop().unwrap().as_num();
    let lhs = stack.pop().unwrap().as_num();
    stack.push(Value::Num(lhs - rhs));
}

fn mul(stack: &mut Vec<Value>){
    let rhs = stack.pop().unwrap().as_num();
    let lhs = stack.pop().unwrap().as_num();
    stack.push(Value::Num(lhs * rhs));
}

fn div(stack: &mut Vec<Value>){
    let rhs = stack.pop().unwrap().as_num();
    let lhs = stack.pop().unwrap().as_num();
    stack.push(Value::Num(lhs / rhs));
}

fn op_if(stack: &mut Vec<Value>) {
    let false_branch = stack.pop().unwrap().to_block();
    let true_branch = stack.pop().unwrap().to_block();
    let cond = stack.pop().unwrap().to_block();

    for code in cond {
        eval(code, stack);
    }

    let cond_result = stack.pop().unwrap().as_num();

    if cond_result != 0 {
        for code in true_branch {
            eval(code, stack);
        }
    } else {
        for code in false_branch {
            eval(code, stack);
        }
    }
}

#[cfg(test)]
mod test {
    use super::{parse, Value::*};
    #[test]
    fn test_group(){
        assert_eq!(
            parse("1 2 + { 3 4 }"),
            vec![Num(3), Block(vec![Num(3), Num(4)])]
        );
    }

    #[test]
    fn test_if_false(){
        assert_eq!(
            parse("{ 1 -1 + } { 100 } { -100 } if"),
            vec![Num(-100)]
        );
    }

    #[test]
    fn test_if_true() {
        assert_eq!(
            parse("{ 1 1 + } { 100 } { -100 } if"),
            vec![Num(100)]
        );
    }
}

Finished `dev` profile [unoptimized + debuginfo] target(s) in 0.03s
Running `target/debug/stackmachine`
{ 100 -100 + } { 100 } { 1 } if
stack: [Num(1)]

【Rust】複数の変数を一度に指定

tuppleを使用する。tuppleは異なる型でも動く。

fn main(){
    let (x, y) = test(100);
    println!("x={}, y={}", x, y);
}

fn test(x: i32)-> (i32, i32) {
    let y = x * 2;
    (x, y)
}

Running `target/debug/sample`
x=100, y=200

fn main(){
    let (x, y, z) = ("hello".to_string(), "world".to_string(), 100);
    println!("x={}, y={}, z={}", x, y, z);
}

Running `target/debug/sample`
x=hello, y=world, z=100

【Rust】構造体のライフタイム注釈

#[derive(Debug)]
struct ImportantExcerpt<'a> {
    part: &'a str,
}

fn main() {
    let novel = String::from("Call me Ishmael. Some years ago...");
    let first_sentence = novel.split('.').next().expect("Could not find a '.'");
    let i = ImportantExcerpt {
        part: first_sentence,
    };
    println!("{:?}", i);
}

Finished `dev` profile [unoptimized + debuginfo] target(s) in 0.26s
Running `target/debug/stackmachine`
ImportantExcerpt { part: “Call me Ishmael” }

なるほど、参照時にライフタイムを指定するのか、、面白いですね。

【Rust】ライフタイムとは

ライフタイムとは、参照が有効になるスコープのこと。
型推論と同じように、ライフタイムがいくつか異なる方法で関係ある場合は注釈を入れなければならない

fn main() {
    let r;

    {
        let x = 5;
        r = &x;
    }

    println!("r: {r:?}");
}

Compiling stackmachine v0.1.0 (/home/vagrant/dev/rust/stackmachine)
error[E0597]: `x` does not live long enough
xはrよりもスコープが短いのでエラーになる

fn main() {
    let string1 = String::from("abcd");
    let string2 = "xyz";

    let result = longest(string1.as_str(), string2);

    println!("The longest string is {result:?}");
}

fn longest(x: &str, y: &str) -> &str {
    if x.len() > y.len() {
        x
    } else {
        y
    }
}

error[E0106]: missing lifetime specifier
–> src/main.rs:10:33
|
10 | fn longest(x: &str, y: &str) -> &str {
| —- —- ^ expected named lifetime parameter

ジェネリックなライフタイム引数を指定された関数は、あらゆるライフタイムの参照を受け取ることができる。

&i32
&’a i32 // 明示的なライフタイム参照
&’a mut i32 // 明示的なライフタイム参照

fn longest<'a>(x: &'a str, y: &'a str) -> &'a str {
    if x.len() > y.len() {
        x
    } else {
        y
    }
}

同じだけライフライむを生きると伝えている

fn main() {
    let string1 = String::from("long string is long");
    let result;
    {
        let string2 = String::from("xyz");
        result = longest(string1.as_str(), string2.as_str());
    }
    println!("The longest string is {result:?}");
    
}

error[E0597]: `string2` does not live long enough
–> src/main.rs:6:44
|
5 | let string2 = String::from(“xyz”);
| ——- binding `string2` declared here
6 | result = longest(string1.as_str(), string2.as_str());
| ^^^^^^^ borrowed value does not live long enough
7 | }
| – `string2` dropped here while still borrowed
8 | println!(“The longest string is {result:?}”);
| ———- borrow later used here

【Rust】スタックベース仮想マシンの基礎

fn main() {
    let mut stack = vec![];

    stack.push(42);
    stack.push(36);

    add(&mut stack);

    println!("stack: {stack:?}");
}

fn add(stack: &mut Vec<i32>){
    let lhs = stack.pop().unwrap();
    let rhs = stack.pop().unwrap();
    stack.push(lhs + rhs);
}

Finished `dev` profile [unoptimized + debuginfo] target(s) in 0.23s
Running `target/debug/stackmachine`
stack: [78]

### 標準入力からの読み込み

fn main() {
    for line in std::io::stdin().lines() {
        if let Ok(line) = line {
            let words: Vec<_> = line.split(" ").collect();
            println!("Line: {words:?}");
        }
    }
}

Finished `dev` profile [unoptimized + debuginfo] target(s) in 0.82s
Running `target/debug/stackmachine`
42 3 +
Line: [“42”, “3”, “+”]

### 文字列のパースと実行

fn main() {
    for line in std::io::stdin().lines() {
        let mut stack = vec![];
        if let Ok(line) = line {
            let words: Vec<_> = line.split(" ").collect();
            
            for word in words {
                if let Ok(parsed) = word.parse::<i32>() {
                    stack.push(parsed);
                } else {
                    match word {
                        "+" => add(&mut stack),
                        _ => panic!("{word:?} could not be parsed"),
                    }
                }
            }
            println!("stadk: {stack:?}");

        }
    }
}

fn add(stack: &mut Vec<i32>){
    let lhs = stack.pop().unwrap();
    let rhs = stack.pop().unwrap();
    stack.push(lhs + rhs);
}

### 四則演算

fn main() {
    for line in std::io::stdin().lines() {
        let mut stack = vec![];
        if let Ok(line) = line {
            let words: Vec<_> = line.split(" ").collect();
            
            for word in words {
                if let Ok(parsed) = word.parse::<i32>() {
                    stack.push(parsed);
                } else {
                    match word {
                        "+" => add(&mut stack),
                        "-" => sub(&mut stack),
                        "*" => mul(&mut stack),
                        "/" => div(&mut stack),
                        _ => panic!("{word:?} could not be parsed"),
                    }
                }
            }
            println!("stadk: {stack:?}");

        }
    }
}

fn add(stack: &mut Vec<i32>){
    let rhs = stack.pop().unwrap();
    let lhs = stack.pop().unwrap();
    stack.push(lhs + rhs);
}

fn sub(stack: &mut Vec<i32>){
    let rhs = stack.pop().unwrap();
    let lhs = stack.pop().unwrap();
    stack.push(lhs - rhs);
}

fn mul(stack: &mut Vec<i32>){
    let rhs = stack.pop().unwrap();
    let lhs = stack.pop().unwrap();
    stack.push(lhs * rhs);
}

fn div(stack: &mut Vec<i32>){
    let rhs = stack.pop().unwrap();
    let lhs = stack.pop().unwrap();
    stack.push(lhs / rhs);
}

【Solana】Proof of HistoryをPythonで書く

前のブロックのiter,hashoutをベースに iter%(2**delay) == 0 になるまで、ブロックごとに262144回sha256を計算して、hash値を求める。hashoutが決まっているので、先回りしてブロックを作れそうだが、SolanaはPoSのため、不正がバレるとstakingが没収されてしまう。なるほどねー

import datetime
import hashlib
import time
import os
import pathlib
import random
import string
from random import randint

iter=1
hashin = ''.join(random.choices(string.ascii_uppercase + string.digits, k = 10))
hashout = hashlib.sha256(hashin.encode()).hexdigest()

print(hashin)
print(hashout)

def datastream():
    v1 = int(randint(1200, 1500))
    v2 = int(randint(1300, 1700))
    v3 = int(randint(1100, 1500))
    v4 = int(randint(4000, 5600))
    v5 = int(randint(4000, 5600))
    v6 = int(randint(1900, 2400))
    v7 = int(randint(1920, 2300))
    v8 = int(randint(1850, 2200))
    v9 = int(randint(1900, 2300))
    v10 = int(randint(1800, 2200))
    return [v1, v2, v3, v4, v5, v6, v7, v8, v9, v10];

class Block:
    blockNo = 0
    count = iter
    data = None
    next = None
    hash = "None"
    previous_hash = "None"
    timestamp = datetime.datetime.now()

    def __init__(self, data):
        self.data = datastream()

    def hash(self):
        file = pathlib.Path("TToken")
        if file.exists():
            tier=open("TToken").readline().rstrip()
        else:
            with open("benchmark.py") as infile:
                exec(infile.read())
            tier=open("TToken").readline().rstrip()

        if tier=="T1":
            h = hashlib.md5()
        elif tier=="T2":
            h = hashlib.sha1()
        elif tier=="T3":
            h = hashlib.blake2s()
        elif tier=="T4":
            h = hashlib.sha3_256()

        h.update(
		str(self.nonce).encode('utf-8') +
		str(self.data).encode('utf-8') +
		str(self.previous_hash).encode('utf-8') +
		str(self.timestamp).encode('utf-8') +
		str(self.blockNo).encode('utf-8')
		)
        return h.hexdigest()
    
        block.blockNo = self.block.blockNo + 1

    def __str__(self):
        return "Block Number: " + str(self.blockNo) + "\nHistory Count: " + str(self.count) + "\nBlock Data: " + str(self.data) + "\nBlock Hash: " + str(self.hash) + "\nPrevious Hash: " + str(self.previous_hash) + "\n--------------"

class Blockchain:
	block = Block("Genesis")
	dummy = head = block

	def add(self, block):
		if (self.block.blockNo ==0):
			block.previous_hash =  "Origin"
		else:
			block.previous_hash = self.block.hash
		block.blockNo = self.block.blockNo + 1

		self.block.next = block
		self.block = self.block.next

	def mine(self, block):
		global iter
		global hashin
		global hashout
		delay = 18
		cont = 1
		while(cont == 1):
			if int(iter%(2**delay) == 0):
				block.count = iter
				block.hash = hashout
				self.add(block)
				print(block)
				iter += 1
				hashin=hashout
				hashout = hashlib.sha256(hashin.encode()).hexdigest()
				cont = 0
				break
			else:
				iter += 1
				hashin=hashout
				hashout = hashlib.sha256(hashin.encode()).hexdigest()

t_initial = time.perf_counter()
blockchain = Blockchain()
b=int(input('Enter the number of Blocks for this simulation:'))

for n in range(b):
    blockchain.mine(Block(n+1))
t_final = time.perf_counter()
delta_t = t_final - t_initial
delta_unit = delta_t*1000/b
print("comutation Time per Block(ms):"+str(delta_unit))
input('Press ENTER to exit')

Enter the number of Blocks for this simulation:3
Block Number: 1
History Count: 262144
Block Data: [1297, 1642, 1372, 5138, 5301, 2188, 1998, 2150, 1914, 1862]
Block Hash: a53e39cef8be27ba38e73fe216fbfc2efc63bca056fa2a6a18380e9d93c98ea3
Previous Hash: Origin
————–
Block Number: 2
History Count: 524288
Block Data: [1211, 1633, 1307, 4757, 5133, 2206, 2032, 1891, 2257, 2139]
Block Hash: 79561ebd2627b432d1e619dee9db7ac85593a4357925827754b1faefd42c1b72
Previous Hash: a53e39cef8be27ba38e73fe216fbfc2efc63bca056fa2a6a18380e9d93c98ea3
————–
Block Number: 3
History Count: 786432
Block Data: [1459, 1682, 1131, 5339, 4983, 2057, 1948, 2192, 2017, 2076]
Block Hash: d33e10fa10273b5d64ccdad34ffcbaae7673cb785807c49f199b204a148e6cd9
Previous Hash: 79561ebd2627b432d1e619dee9db7ac85593a4357925827754b1faefd42c1b72
————–
comutation Time per Block(ms):795.6611973543962
Press ENTER to exit

Linuxカーネルのメモリ管理とメモリの割当て

カーネルのメモリ管理システムの機能によって管理している。

メモリの割当ては
– プロセスの生成時
– プロセス生成後、追加で動的にメモリ割当て(メモリ獲得用のシステムコール発動)

### 仮想メモリ
プロセスから見えるメモリを仮想メモリ
システムに搭載されている実際のアドレスを物理メモリと呼ぶ
仮想アドレスを用いて、間接的にアクセスさせる(プロセスから実際のメモリには直接アクセスしない)
=> 仮想アドレスのページテーブルに、物理アドレスのアドレスが入っている

#include <stdio.h>
#include <stdlib.h>

int main(void) {
    int *p = NULL;
    puts("before invalid access");
    *p = 0;
    puts("after invalid access");
    exit(EXIT_SUCCESS);
}

$ ./main
before invalid access
Segmentation fault (core dumped)

### プロセスへのメモリ割当て
仮想アドレスと物理アドレスをマッピングして実行

#include <unistd.h>
#include <sys/mman.h>
#include <stdio.h>
#include <stdlib.h>
#include <err.h>

#define BUFFER_SIZE 1000
#define ALLOC_SIZE (100*1024*1024)

static char command[BUFFER_SIZE];

int main(void) {
    pid_t pid;

    pid = getpid();
    snprintf(command, BUFFER_SIZE, "cat /proc/%d/maps", pid);

    puts("*** memory map before memory allocation ***");
    fflush(stdout);
    system(command);

    void *new_memory;
    new_memory = mmap(NULL, ALLOC_SIZE, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
    if (new_memory == (void *) -1)
        err(EXIT_FAILURE, "mmap() failed");

    puts("");
    printf("*** succeeded to allocate memory: address = %p; size = 0x%x ***\n", new_memory, ALLOC_SIZE);
    puts("");

    puts("*** memory map after memory allocation ***");
    fflush(stdout);
    system(command);

    if(munmap(new_memory, ALLOC_SIZE) == -1)
        err(EXIT_FAILURE, "munmap() failed");
    exit(EXIT_SUCCESS);
}

$ ./main
*** memory map before memory allocation ***
aaaabbfc0000-aaaabbfc1000 r-xp 00000000 fd:00 1125982 /home/vagrant/dev/work/stackmachine/main
aaaabbfd0000-aaaabbfd1000 r–p 00000000 fd:00 1125982 /home/vagrant/dev/work/stackmachine/main
aaaabbfd1000-aaaabbfd2000 rw-p 00001000 fd:00 1125982 /home/vagrant/dev/work/stackmachine/main
aaaac367f000-aaaac36a0000 rw-p 00000000 00:00 0 [heap]
ffff8fed0000-ffff90058000 r-xp 00000000 fd:00 788338 /usr/lib/aarch64-linux-gnu/libc.so.6
ffff90058000-ffff90067000 —p 00188000 fd:00 788338 /usr/lib/aarch64-linux-gnu/libc.so.6
ffff90067000-ffff9006b000 r–p 00187000 fd:00 788338 /usr/lib/aarch64-linux-gnu/libc.so.6
ffff9006b000-ffff9006d000 rw-p 0018b000 fd:00 788338 /usr/lib/aarch64-linux-gnu/libc.so.6
ffff9006d000-ffff90079000 rw-p 00000000 00:00 0
ffff9008c000-ffff900b7000 r-xp 00000000 fd:00 788335 /usr/lib/aarch64-linux-gnu/ld-linux-aarch64.so.1
ffff900c1000-ffff900c3000 rw-p 00000000 00:00 0
ffff900c3000-ffff900c5000 r–p 00000000 00:00 0 [vvar]
ffff900c5000-ffff900c6000 r-xp 00000000 00:00 0 [vdso]
ffff900c6000-ffff900c8000 r–p 0002a000 fd:00 788335 /usr/lib/aarch64-linux-gnu/ld-linux-aarch64.so.1
ffff900c8000-ffff900ca000 rw-p 0002c000 fd:00 788335 /usr/lib/aarch64-linux-gnu/ld-linux-aarch64.so.1
ffffd9144000-ffffd9165000 rw-p 00000000 00:00 0 [stack]

*** succeeded to allocate memory: address = 0xffff89ad0000; size = 0x6400000 ***

*** memory map after memory allocation ***
aaaabbfc0000-aaaabbfc1000 r-xp 00000000 fd:00 1125982 /home/vagrant/dev/work/stackmachine/main
aaaabbfd0000-aaaabbfd1000 r–p 00000000 fd:00 1125982 /home/vagrant/dev/work/stackmachine/main
aaaabbfd1000-aaaabbfd2000 rw-p 00001000 fd:00 1125982 /home/vagrant/dev/work/stackmachine/main
aaaac367f000-aaaac36a0000 rw-p 00000000 00:00 0 [heap]
ffff89ad0000-ffff8fed0000 rw-p 00000000 00:00 0
ffff8fed0000-ffff90058000 r-xp 00000000 fd:00 788338 /usr/lib/aarch64-linux-gnu/libc.so.6
ffff90058000-ffff90067000 —p 00188000 fd:00 788338 /usr/lib/aarch64-linux-gnu/libc.so.6
ffff90067000-ffff9006b000 r–p 00187000 fd:00 788338 /usr/lib/aarch64-linux-gnu/libc.so.6
ffff9006b000-ffff9006d000 rw-p 0018b000 fd:00 788338 /usr/lib/aarch64-linux-gnu/libc.so.6
ffff9006d000-ffff90079000 rw-p 00000000 00:00 0
ffff9008c000-ffff900b7000 r-xp 00000000 fd:00 788335 /usr/lib/aarch64-linux-gnu/ld-linux-aarch64.so.1
ffff900c1000-ffff900c3000 rw-p 00000000 00:00 0
ffff900c3000-ffff900c5000 r–p 00000000 00:00 0 [vvar]
ffff900c5000-ffff900c6000 r-xp 00000000 00:00 0 [vdso]
ffff900c6000-ffff900c8000 r–p 0002a000 fd:00 788335 /usr/lib/aarch64-linux-gnu/ld-linux-aarch64.so.1
ffff900c8000-ffff900ca000 rw-p 0002c000 fd:00 788335 /usr/lib/aarch64-linux-gnu/ld-linux-aarch64.so.1
ffffd9144000-ffffd9165000 rw-p 00000000 00:00 0 [stack]