【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]

execve()関数

実行ファイルは、
– コードを含むデータ領域のファイル上のオフセット、サイズ、メモリマップ開始アドレス
– 最初に実行する命令のメモリアドレス(エントリポイント)
を持っている。

100 オフセット(基準点)
100 サイズ
300 メモリマップ開始アドレス
200 データオフセット
200 データサイズ
400 メモリマップ開始アドレス
400 エントリポイント(エントリポイントからプログラム開始)

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

static void child(){
    char *args[] = {"/bin/echo", "hello", NULL};
    printf("I'm child! my pid is %d.\n", getpid());
    fflush(stdout);
    execve("/bin/echo", args, NULL);
    err(EXIT_FAILURE, "exec() failed");
}

static void parent(pid_t pid_c) {
    printf("I'm parent! my pid is %d and the pid of my child is %d.\n", getpid(), pid_c);
    exit(EXIT_SUCCESS);
}

int main(void) {
    pid_t ret;
    ret = fork();
    if (ret == -1)
        err(EXIT_FAILURE, "fork() failed");
    if (ret == 0) {
        child();
    } else {
        parent(ret);
    }
    err(EXIT_FAILURE, "shouldn't reach here");
}

$ ./fork
I’m parent! my pid is 314918 and the pid of my child is 314919.
I’m child! my pid is 314919.
hello

スタックマシンの場合はpushとpupだが、この場合はオフセット、サイズ、エントリポイント、メモリ(レジスタ)の番地を指定している。逆に言えば、スタックの場合は順番に気をつけなければならないが、オフセットなどを指定できる場合はより柔軟に対応できるということか。

Linuxのプロセス生成

Linuxのプロセス生成にはfork() ※clone(), execve()の2つのシステムコールがある。

同じプログラムの処理を複数のプロセスに分けるのはfork()
– プロセスを新規作成

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

static void child(){
    printf("I'm child! my pid is %d.\n", getpid());
    exit(EXIT_SUCCESS);
}

static void parent(pid_t pid_c) {
    printf("I'm parent! my pid is %d and the pid of my child is %d.\n", getpid(), pid_c);
    exit(EXIT_SUCCESS);
}

int main(void) {
    pid_t ret;
    ret = fork();
    if (ret == -1)
        err(EXIT_FAILURE, "fork() failed");
    if (ret == 0) {
        child();
    } else {
        parent(ret);
    }
    err(EXIT_FAILURE, "shouldn't reach here");
}

$ ./fork
I’m child! my pid is 314564.
I’m parent! my pid is 314563 and the pid of my child is 314564.

システムコールのラッパー関数

システムコールはアーキテクチャ依存のアセンブリコードを使って呼び出す

$ ldd /bin/echo
linux-vdso.so.1 (0x0000ffffb992d000)
libc.so.6 => /lib/aarch64-linux-gnu/libc.so.6 (0x0000ffffb9720000)
/lib/ld-linux-aarch64.so.1 (0x0000ffffb98f4000)

$ ldd /usr/bin/python3
linux-vdso.so.1 (0x0000ffffb5233000)
libm.so.6 => /lib/aarch64-linux-gnu/libm.so.6 (0x0000ffffb4b90000)
libexpat.so.1 => /lib/aarch64-linux-gnu/libexpat.so.1 (0x0000ffffb4b50000)
libz.so.1 => /lib/aarch64-linux-gnu/libz.so.1 (0x0000ffffb4b20000)
libc.so.6 => /lib/aarch64-linux-gnu/libc.so.6 (0x0000ffffb4970000)
/lib/ld-linux-aarch64.so.1 (0x0000ffffb51fa000)

pythonは内部的に標準のclibraryを使っている。libcというのがcライブラリ
OSが提供するプログラムの一例として
init, sysctl, nice, sync, touch, mkidr, grep, sort, uniq, sar, iostat, gcc, perl, python, ruby, bash などがある。

【C】システムコール呼び出しの仕組み

### C言語の場合

#include <stdio.h>

int main(void) {
    puts("hello world");
    return 0;
}

$ strace -o hello.log ./hello
hello world

$ cat hello.log
execve(“./hello”, [“./hello”], 0xffffda929930 /* 42 vars */) = 0
brk(NULL) = 0xaaab00641000
mmap(NULL, 8192, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0xffff9126e000
faccessat(AT_FDCWD, “/etc/ld.so.preload”, R_OK) = -1 ENOENT (No such file or directory)
openat(AT_FDCWD, “/etc/ld.so.cache”, O_RDONLY|O_CLOEXEC) = 3
newfstatat(3, “”, {st_mode=S_IFREG|0644, st_size=48255, …}, AT_EMPTY_PATH) = 0
mmap(NULL, 48255, PROT_READ, MAP_PRIVATE, 3, 0) = 0xffff9122d000
close(3) = 0
openat(AT_FDCWD, “/lib/aarch64-linux-gnu/libc.so.6”, O_RDONLY|O_CLOEXEC) = 3
read(3, “\177ELF\2\1\1\3\0\0\0\0\0\0\0\0\3\0\267\0\1\0\0\0\340u\2\0\0\0\0\0″…, 832) = 832
newfstatat(3, “”, {st_mode=S_IFREG|0755, st_size=1637400, …}, AT_EMPTY_PATH) = 0
mmap(NULL, 1805928, PROT_NONE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0xffff91074000
mmap(0xffff91080000, 1740392, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0) = 0xffff91080000
munmap(0xffff91074000, 49152) = 0
munmap(0xffff91229000, 15976) = 0
mprotect(0xffff91208000, 61440, PROT_NONE) = 0
mmap(0xffff91217000, 24576, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x187000) = 0xffff91217000
mmap(0xffff9121d000, 48744, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0) = 0xffff9121d000
close(3) = 0
set_tid_address(0xffff9126ef30) = 313040
set_robust_list(0xffff9126ef40, 24) = 0
rseq(0xffff9126f600, 0x20, 0, 0xd428bc00) = 0
mprotect(0xffff91217000, 16384, PROT_READ) = 0
mprotect(0xaaaac9350000, 4096, PROT_READ) = 0
mprotect(0xffff91273000, 8192, PROT_READ) = 0
prlimit64(0, RLIMIT_STACK, NULL, {rlim_cur=8192*1024, rlim_max=RLIM64_INFINITY}) = 0
munmap(0xffff9122d000, 48255) = 0
newfstatat(1, “”, {st_mode=S_IFCHR|0620, st_rdev=makedev(0x88, 0x3), …}, AT_EMPTY_PATH) = 0
getrandom(“\xbf\x00\x96\xce\x0e\x82\xcd\xa2”, 8, GRND_NONBLOCK) = 8
brk(NULL) = 0xaaab00641000
brk(0xaaab00662000) = 0xaaab00662000
write(1, “hello world\n”, 12) = 12
exit_group(0) = ?
+++ exited with 0 +++

色々はかれていますが、write()がシステムコールです。
write(1, “hello world\n”, 12) = 12

### Pythonの場合

#include <stdio.h>

int main(void) {
    puts("hello world");
    return 0;
}

$ strace -o hello.py python3 ./hello.py

システムコールってよく聞くけど、システムコールの理解が深まった気がする。

Average: CPU %user %nice %system %iowait %steal %idle
Average: all 1.62 0.00 1.69 0.19 0.00 96.50
Average: 0 1.56 0.00 1.79 0.11 0.00 96.54
Average: 1 1.68 0.00 1.60 0.26 0.00 96.46

ユーザモードはuser, niceで systemがカーネルモード、idelは何も動いていない状態です。

【React.js】Base64 encodeとdecodeをReactで実装する

import React, {useState} from 'react';
 
const App = () => {
    /* ↓state変数を定義 */
    const [encode_text, setText] = useState("");
    const input = {
        width: "80%",
    }
    let msg = '文字列を入力してください';
  
    return (
      <div className="App">
        <h6 class="card-subtitle mb-2 text-body-secondary">Base64 Encode</h6>
        <input
        value={encode_text}
        onChange={(event) => setText(event.target.value)} style={input} placeholder={msg}
        />
        <p>{btoa(encode_text)}</p><br />
      </div>
    );
};
export default App;

なるほど〜