プログラミングのゴミ箱

日々の学習の中で知らなかったことについて、調べたことを解説します。

Ethereum入門読んでみた③

この記事は前回の続きです。
chanichiwasshoi.hateblo.jp

このページを読んでます。
etherを採掘する - Ethereum入門

Gethとは

GethとはEthereumネットワークに参加するためのCUIクライアントでのことです。Gethを通じて

などの動作が可能となります。

Ethereumコンソールへの接続

※gethのインストールや初期化などは記事を見て行ってください。
なんやかんやでGethをインストールして起動ができたら、ターミナルで次のコマンドを実行してコンソールを起動してください。

geth --networkid "15" --nodiscover --datadir "." console 2>> ./geth_err.log

すると、Gethのコンソールが起動しコマンドが打てるようになります。試しに以下のコマンドを実行してGenesisブロック(一番最初のブロック)の中身を確認してください。

> eth.getBlock(0)

{
  difficulty: 16384,
  extraData: "0x00",
  gasLimit: 134217728,
(中略)
  miner: "0x3333333333333333333333333333333333333333",
  nonce: "0x0000000000000042",
  number: 0,
  parentHash: "0x0000000000000000000000000000000000000000000000000000000000000000",
(後略)
}

アカウント関連のコマンド

1. EOAの確認

> eth.accounts
['0x23233...', '0xd1938..."]

EOAの作成

> personal.newAccount("some_password")
'0x2f841a...'

マイニング報酬を受け取るアカウント

//報酬を受け取るアカウントの確認
> eth.coinbase 
'0x819f01...'


//報酬を受け取るアカウントの変更
> miner.setEtherbase(eth.accounts[1])

etherの採掘

// 採掘の開始
> miner.start()
null

//採掘の停止
> miner.stop()
true

// 採掘されたブロック数
> eth.blockNumber
145

// 採掘中かどうか確認
> eth.mining
true

// 採掘速度の確認
> eth.hashrate
445445

採掘したブロックの内容を調べる

> eth.getBlock(100)
{
  difficulty: '137447',
  extraData: '0x476574682f76312e302e312f6c696e75782f676f312e342e32',
  gasLimit: 3141592,
  gasUsed: 0,
  hash: '0x4d3063b91cbaa12bf2de81014c1319febc9f197c93f81b0746afaffaa9496620',
  logsBloom: '0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000',
  miner: '0x24afe6c0c64821349bc1bfa73110512b33fa18e1',
  nonce: '0x28fda83cb19ed497',
  number: 100,
  parentHash: '0x5885cdec1d1410580eaaf1fb7ef9db245a735822d48e816c73d926b7c9872f15',
  sha3Uncles: '0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347',
  size: 536,
  stateRoot: '0xacf2c3dfc512373ae6d9693207b3ac43fd4811791fec994c2eecd8fdd3333699',
  timestamp: 1439451765,
  totalDifficulty: '13551548',
  transactions: [ ],
  transactionsRoot: '0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421',
  uncles: [ ]
}
> eth.getBlock(101)
{
  difficulty: '137514',
  extraData: '0x476574682f76312e302e312f6c696e75782f676f312e342e32',
  gasLimit: 3141592,
  gasUsed: 0,
  hash: '0xca9b241dabe753ed83d6242f226c0ad6b559c722edf5d24baff126670f70a30c',
...
 }

報酬の確認

> eth.getBalance(eth.accounts[0])
' 51500000000000'

Ethereum入門読んでみた②

この記事は前回の記事の続きです。
chanichiwasshoi.hateblo.jp
以下の記事を読んだ備忘録的なところを書いていきます。
Ethereumとは - Ethereum入門

Ethereumとは

Ethereumが登場する以前のブロックチェーンアプリ開発方法は主に次の2つであった。

しかし、独自に新たなブロックチェーンを開発するのはコストが掛かりすぎるし、ビットコイン上にサービスを作るとビットコインの設計による制限を受ける(ブロックの生成間隔が遅い。取引に関するデータしか扱えない など)。
そこで、誰でも簡単に分散アプリの開発が出来ることを目標に作られたのがEthereum。

Bitcoinとの違い

アカウント

 Bitcoinでは個人のデータをUTXOという形で管理していたが、Ethereumではアカウントという形で管理している。UTXOとの違いはUTXOはトランザクションの履歴を保存おり、その履歴から現在保有しているBitcoinの量を計算していたが、アカウントでは現在保有しているEthereumの量を直接管理しており、残高計算のコストがほぼ0になっている。
 アカウントは20Byteのアドレスにより参照されており、主に以下の4つのフィールドを持つ。

  • nonce: そのアカウントが送信した累積トランザクション
  • ether balance: そのアカウントが所有するether量
  • contract code: コントラクト・コード
  • storage: そのアカウントが保持する任意のデータ

 アカウントには「Externally Owned Account(EOA)」,「Contract」という2つのタイプが存在する。ContractはEOAが発信するトランザクションをトリガに、コントラクト・コードを実行する。

EOAはユーザーにより生成されるが、ContractはEOAにより生成される。

トランザクション

Ethereumのトランザクションは主に以下の情報を含む。

  • ether送金額
  • 相手先アドレス
  • 送信アカウント署名
  • 任意データ
  • STARTGAS値
  • GASPRICE値

 任意データは、送り先がContractである場合にそのコントラクト・コードに引き渡すデータを格納する。
 STARTGAS値と、GASPRICE値は、トランザクションの手数料として支払うetherの量を規定する情報。Ethereumでは実行するコードの量に応じて手数料を払う仕組みにすることで、システムが止まってしまうような致命的なコードが実行されることを避ける様になっている。
 手数料の支払いにはgasという単位を使用し、STARTGAS値がトランザクションで支払う最大のgas量。GASPRICE値がgasと内部通貨etherとの交換レートを表している。

Ethereum入門を読んでみた①

https://book.ethereum-jp.net/what_is_ethereum/blockchainrev_md

UTXO(Unspent Transaction Output)とは?

まだ他の誰かに送るために使用されていないトランザクションのこと。
あるユーザーの保有BTC量は、そのユーザーに向けられたUTXOの総和によって求められる。
例えば太郎さんに、次郎さんから20BTC、三郎さんから10BTCをもらうというUTXOが向けられているとする。
そうすると、太郎さんの持っているBTCは合計で30BTCである。

さらに、太郎さんは25BTCを花子さんに渡したとする。
しかし、UTXOは単なるトランザクションの履歴であるため分割できず、10BTCと20BTCでは25BTCを表現できない。
そこで太郎さんは、25BTCを花子さんに送金し、5BTCを自分に送金するというUTXOを作成する。
こうすることで太郎さんはUTXOを分割することなく正しく送金ができる。


マイニング

ブロックチェーンにブロックを追加することをマイニングという。
マイナーはブロックを追加するときに

  • UTXOの所有者意外がそのUTXOを使って送金していないか
  • 同じUTXOを複数回使用するようなトランザクションは無いか

などを確認する。

二重支払い問題の対応

例えば、以下のようなケースを考える。

  1. 攻撃者が、あるEC業者から商品を購入し100BTCを送金する。
  2. EC業者は100BTCが送金されたことをブロックチェーンの記録を見て確認する。送金されたことが確認できたら商品を発送する。
  3. 攻撃者が商品を受け取る。
  4. 攻撃者が業者に支払った100BTCをなかったことにするために、同じ100BTCを自分自身に送金したというように、ブロックチェーンを書き換える。

仮に、1の送金が2000番のブロックに記録されていたとする。
2000番ブロックを書き換えると、その後の2001番以降のブロックの値も書き換わるため後ろに続くすべてのブロックのnonceを探さなければならない。
書き換えが行われるとチェーンは2000番の場所でforkする。
チェーンは長いほうが正しいと認識されるため、悪意のあるユーザーの計算力が51%を超えない限りはブロックの書き換えは成立しない。


ブロックチェーンの仕組み

EnterChain(https://enterchain.online/home)のPhase1で学習したことの備忘録。

ブロックチェーンとは

 データの改竄を不可能(困難)にする技術。その応用性の高さから様々なビジネスに結び付けられることが期待される。
 一般的にはビットコインなどの暗号資産と共に知られているが、ブロックチェーン = 暗号資産ではない。
 ブロックチェーンの公開範囲によってパプリックチェーン(全ての人に公開)とコンソーシアムチェーン(複数企業に公開)、プライベートチェーン(単一企業のみで使用)というふうに分類され、暗号資産はパブリックチェーンに分類される。

ブロックチェーンの仕組み

 ブロックチェーンに記述されるいくつかのデータをまとめたものをブロックと呼び、ブロックの中にはデータとNonce(Number used once)、前のブロックのハッシュ値が格納される。
 ハッシュ値とはハッシュ関数と呼ばれる関数によって生成される値のことを指し、ハッシュ関数はいかの特徴を持っている。

  1. 関数を通したあとのデータからは、元のデータがなにかわからない。
  2. どんなデータをハッシュ化しても、同じ長さのハッシュ値になる。
  3. 同じデータを何度ハッシュ化しても、常に同じハッシュ値になる。

 新しいブロックを生成するには、先程の3つのデータをハッシュ化した値の先頭の何文字かが0となるように調整されたNonceを見つけなければならず、ビットコインでは条件を満たすNonceを見つけた人に報酬としてビットコインが支払われる。
 それぞれのブロックは前のブロックのハッシュ値を持っているため、データを改ざんしようとするとそれ以降につながっているすべてのブロックのNonceを見つけなければならず、Nonceの発見には膨大な計算量が必要となるため、改ざんが困難な仕組みとなっている。

ブロックチェーンのメリット・デメリット

メリット

  • 非中央集権的にデータを管理出来る(第三者を介さず個人間の取引が実現できる)。
  • サービスが停止しにくい(ゼロダウンタイム)。
  • トレーサビリティが高い(データの行方が追える)。

デメリット

  • 最初に入力されるデータが誤りだった場合に見抜くことができない(オラクル問題)。
  • 処理速度が遅い(スケーラビリティ問題)。

 スケーラビリティの問題については様々な解決策が考案されている。
 例えば、ビットコインでは10分に一つのブロックが生成されるが、これを単純に5秒に一つにすると、処理速度は120倍になる。
 しかし、ブロックの生成間隔を短くすることで新たな問題が生まれる。それは、異なる人が同時にマイニング(Nonceを見つける作業)を行う確率が高くなってしまうことである。
 もし複数人が同時にマイニングを行った場合、チェーンを分岐させることで対応する。複数のチェーンが同時に存在する環境を作り出し、あとからチェーンの長い方をメインのチェーンとするというものである。これをフォークという。
 ブロックの生成感覚を短くしてしまうとフォークされたチェーンがたくさん存在することになり、チェーンが複雑になってしまう可能性がある。
 処理速度とチェーンの管理のしやすさのバランスを取らなければならない。

Ethereum(イーサリアム)

 イーサリアムにはスマートコントラクトと呼ばれる機能があり、ブロックチェーン上でプログラムを自動で実行してくれる。この機能のおかげで、イーサリアムは単なる通貨としてではなく、様々なアプリケーションを開発するプラットフォームとなっている。
 スマートコントラクトを操作するためのツールとしてSolidityという言語が有名である。

WebSocket connection to 'ws://localhost:3000/ws' failed: と言われたら<React>

Reactを使ってアプリを使っていると[WebSocket connection to 'ws://localhost:3000/ws' failed: ]と怒られた。
原因が分からなくて放置していたけど、流石にエラーがうるさいので対応することにした。

環境としてはDockerを使って、3000番ポートのReactアプリを8000番ポートに対応させ、Railsサーバーを3000番ポートで動かしていた。

原因はここにあった。React側は自分が3000番ポートで動いていると思っているため、何かしらの処理に必要なWebSocket通信を自分自身に要求している。
しかし、3000番ポートではRailsサーバーが動いているためWebSocketに接続できずよくわからない挙動をしていたのだ。
対応としては、Railsサーバーを3001番ポートとかで動かして、Reactを3000番ポートで動かす。
もしくはReactを最初から8000番ポートで動かす必要がある。

サンプルプログラムで学ぶPHPでExcel操作(初心者向け) 前編

目的

PhpSpreadsheetを使ってPHPExcelを操作する方法をゴリラでもわかるようにサンプルプログラムを作りながら解説。
f:id:chanichiwasshoi:20220101134302p:plain
f:id:chanichiwasshoi:20220101134605p:plain

こんな感じのアプリができます。

PhpSpreadsheetって?

Phpを使ってExcelを操作するためのライブラリです。
大昔にPHPExcelというライブラリも存在したらしいんですけど、今完全にPhpSpreadsheetに移り変わっています。
github.com

公式もPHPSpreadsheetを使うように言ってます。

環境構築

まずはPHPSpreadsheetを環境に追加します。
PHPで環境構築をするときにはcomposerというものを使います。JavaScriptで言うところのnpmです。
composerのインストール方法についてはこちらを参照しました。
www.webdesignleaves.com

composerがインストールできたら、PHPSpreadsheetを使いたいフォルダの下に移動して、以下のコマンドを実行します。
Welcome to PhpSpreadsheet's documentation - PhpSpreadsheet Documentation

mkdir PHPサンプルフォーム
cd PHPサンプルフォーム
composer require phpoffice/phpspreadsheet

PHPSpreadsheetのインストールが完了しました!!
プログラムを作っていきましょう!

Excelファイルの読み込み

まずはExcelファイルを読み込んでいきます。
 今回使用プログラムはgithub上に公開していますので、Excelファイルを使用する場合はこちらからダウンロードしてください。
GitHub - trmti/PHP-Sample-form: PHPを用いたExcel操作のサンプルプログラム
大したことは書いてないのでExcelファイルは自作してもらって全然構いません笑。

Excelを読み込むために以下のようなプログラムを作ります。

require 'vendor/autoload.php'; // ライブラリの読み込み

use PhpOffice\PhpSpreadsheet\Reader\Xlsx as XlsxReader;
$inputFileName = "./SampleForm.xlsx";
$reader = new XlsxReader();
$spreadsheet = $reader->load($inputFileName);
$sheet = $spreadsheet->getSheet(0);
echo $sheet->getCell("C3")->getValue(); // 176

プログラムの解説をします。
 まず一行目のrequireの場所ではcomposerを使ってインストールしたライブラリをすべて読みこんで使えるようにしています。ここは定型文なのでふーんくらいに思っていてください。詳しく知りたい方を以下のサイトなどを参照したらいいと思います。
これで理解できるPHPのComposerを使ったオートロード | アールエフェクト

 次のuseのところでは実際にどのライブラリを使うのかnamespaceを使って指定しています。namespaceはこのサイトがわかりやすいです。
【PHP超入門】名前空間(namespace・use)について - Qiita
 簡単に言うと、いろんなプログラムを読み込んでしまうと関数名がかぶったりごちゃごちゃしたりしてわかりにくくなってしまうから、フォルダ分けするように関数やクラスにパスを付けましょうみたいなことです。
asをつけることでそのパスを変数に代入して使えます。

 ここで注意してほしいのが、読み込むファイルがxlsxファイルの場合はこのままで大丈夫ですが、xlsファイルの場合パスを
PhpOffice\PhpSpreadsheet\Reader\Xls
に変更してください。僕はこれに気がつくのに1時間かかりました笑。

 あとは$spreadsheetでExcelファイルを読み込み、$sheetでどのシートからデータを取るかを選択し、シートのC3の値を出力しています。

関数化

次にこのプログラムを関数化して使いやすくします。readExcel.phpというファイルを作って以下のようなプログラムを書いてください。

<?php

require 'vendor/autoload.php';

use PhpOffice\PhpSpreadsheet\Reader\Xlsx as XlsxReader;

function getData(
  $data_range,
  $sheetNum = 0,
  $inputFileName = "./SampleForm.xlsx",
) {
  $reader = new XlsxReader();
  $spreadsheet = $reader->load($inputFileName);
  $sheet = $spreadsheet->getSheet($sheetNum);
  $dataArray = $sheet->rangeToArray(
    $data_range,
    NULL, // からのセルにNULLを代入
    TRUE, // 値を計算してから返すかどうか ex.2*A3を計算するかそのまま返すか
    TRUE, // 値をフォーマットして返すか(ここはよくわからんかった)
    TRUE, // 配列にインデックス名を与えて返すか
  );
  return $dataArray;
}
?>

さっきのプログラムとの変更点は単一のデータを返すのではなく、二次元配列のデータを返しているところです。
例えば、$data_rangeに"A3:D8"という値を与えると、A3からD8までの範囲のデータを取得し、$data["A"][4]というようにアクセスできます。

これでPHPからExcelの値を取得できるようになりました。

React+TypeScriptな環境を作る

1. プロジェクトの作成

npm i -g create-react-app
create-react-app react-app --template typescript

これで基本的な環境は完成。楽勝。

2 import文をを絶対パスで指定できるようにする。

tsconfig.jsonを以下のように編集

{
  "compilerOptions": {
...
    "baseUrl": "src"
  },
  "include": ["src"]
}

これで絶対パスが指定できるようになる。
後はお好みにどうぞ