[Ethereum] DDTによる初めてのスマートコントラクト

$ truffle init
$ tree
.
├── contracts
│   └── Migrations.sol
├── migrations
│   └── 1_initial_migration.js
├── test
└── truffle-config.js

Compile: truffle compile
Migrate: truffle migrate
Test contracts: truffle test

test/greeter_test.js

const GreeterContract = artifacts.require("Greeter");

contract("Greeter", () => {
	it("has been deployed successfully", async() => {
		const greeter = await GreeterContract.deployed();
		assert(greeter, "contract was not deployed");
	});
});

$ sudo truffle test

Compiling your contracts…
===========================
> Compiling ./contracts/Migrations.sol
> Artifacts written to /tmp/test-20211113-60133-1nsib01.f2gyk
> Compiled successfully using:
– solc: 0.5.16+commit.9c3226ce.Emscripten.clang

Error: Could not find artifacts for Greeter from any sources

contracts/Greeter.sol

pragma solidity >= 0.4.0 < 0.7.0;

contract Greeter {
	
}

$ truffle test

Compiling your contracts…
===========================
> Compiling ./contracts/Greeter.sol
> Compiling ./contracts/Migrations.sol
> Artifacts written to /tmp/test-20211113-60435-1cj02xv.58fvg
> Compiled successfully using:
– solc: 0.5.16+commit.9c3226ce.Emscripten.clang

Contract: Greeter
1) has been deployed successfully
> No events were emitted

truffle testを実行するたびにコントラクトをコンパイルしてテストネットワークにデプロイする
ネットワークに追加するにはマイグレーションを作成する必要がある

migrations/2_deploy_greeter.js

const GreeterContract = artifacts.require("Greeter");

module.exports = function(deployer){
	deployer.deploy(GreeterContract);
}

$ truffle test

Compiling your contracts…
===========================
> Compiling ./contracts/Greeter.sol
> Compiling ./contracts/Migrations.sol
> Artifacts written to /tmp/test-20211113-63614-1lnqpgc.prxq
> Compiled successfully using:
– solc: 0.5.16+commit.9c3226ce.Emscripten.clang

Contract: Greeter
✓ has been deployed successfully

1 passing (42ms)

contactをデプロイすると、テストをパスする

[Ethereum] 開発環境の準備

イーサリアムクライアントとNode.jsを使う
Node.jsはTuffle用のJS環境
ブロックチェーンとのやりとりはJSON-RPCを使う
今回はParityを使う

### Parityのインストール(ubuntu)

$ bash <(curl https://get.parity.io -L)
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
  0     0    0     0    0     0      0      0 --:--:-- --:--:-- --:--:--     0curl: (6) Could not resolve host: get.parity.io

あれ…

### Parityのインストール(ubuntu)
$ sudo apt update
$ sudo apt install snapd
$ sudo snap install parity
parity v2.7.2 from Parity DevOps (devops-parity) installed

動作テスト
$ parity –chain=goerli
2021-12-13 02:44:58 UTC Starting Parity-Ethereum/v2.7.2-stable-2662d19-20200206/x86_64-unknown-linux-gnu/rustc1.41.0
2021-12-13 02:44:58 UTC Keys path /home/vagrant/snap/parity/16707/.local/share/io.parity.ethereum/keys/goerli
2021-12-13 02:44:58 UTC DB path /home/vagrant/snap/parity/16707/.local/share/io.parity.ethereum/chains/goerli/db/b1d518969eab529d
2021-12-13 02:44:58 UTC State DB configuration: fast
2021-12-13 02:44:58 UTC Operating mode: active
2021-12-13 02:44:59 UTC Configured for Görli Testnet using Clique engine

### MetaMask
JSON-RPCを通じてブロックチェーンのやり取りをする
12単語のハーモニックを格納できる

### node.js
$ curl -sL https://deb.nodesource.com/setup_14.x -o nodesource_setup.sh
$ sudo bash nodesource_setup.sh
$ sudo apt install nodejs
$ node -v
v14.18.2

### Truffle Suite
$ npm install -g truffle@5.1.31
// npm install -g truffle

### Ganache
自分専用のブロックチェーンであり、JSON-RPCサーバを実行する

なんだこれえええええええええええええ

[Ethereum] 基礎

– EVM上で動く 
– Solidityはスマートコントラクトの開発によく使われている
– イーサリアムが評価されたのはスマートコントラクトをデプロイ・実行するためのプラットフォームを提供した為
– 世界中のイーサリアムノードで接続している
– パブリックイーサリアムネットワークに接続するには、ブルーノード(信頼性の高いIP)のリストがある
– フォークした場合、最も長いチェーンが勝つ
– Proof-of-stake: Ethereumを提供する
– トランザクション手数料をガスと言う
– トランザクションの処理は13秒に1つ程度
– メモリプールが起きた場合、高いガスを払うと、処理される
– メモリプールに複数のトランザクションが含まれている場合、ブロック作成者はナンスによってトランザクションを決める
– チェーンに新しいブロックが追加されてからトランザクションが確定
– ハードフォークを行なうときは議論になり、2016年のハードフォークで以前のプロトコルをイーサリアムクラシックと呼ぶ
– 1Gweiは10億ウェイで1イーサ
– プアブリックイーサリアムネットワークはmainnet、ステージング環境はtestnetでfaucetという無料配布の仕組みがある
– EVMのオペコードはPUSH1、MLOADといった命令があり、ガス費用が割り当てられる
– gasPriceを設定することができる フロントランニングでgasPriceを設定する
– gas属性とgasPrice属性が含まれていないといけない

### アカウント
– 基本的トランザクションはEOA間でのイーサ送金

### コントラクト
オブジェクト指向スタイル、 状態変数と関数
読み取り変数をpureとview

### ブロック作成者とトランザクション
gasPrice, origin, data, sender, sig, value, number, timestamp, blockhash, difficulty, gaslimit, coinbase
ブロック作成者はトランザクションの順序を操作できる

### トランザクション署名
秘密鍵、暗号署名はMetaMaskというウォレットソフトウェアに任せる
nonce, gasPrice, gas, to, value, data, chainId

### トークン
所有権を意味する

– ERC-20
相互に交換可能
totalSupply(), balanceOf(address _owner), transfer(address _to, unit256 _value), transferFrom(address _from, address _to, unit256 _value), approve(address _spender, unit256 _value), allowance(address _owner, address _spender)

– ERC-721
互いに異なっているトークン
balanceOf(address _owner), ownerOf(unit256 _tokenId), safeTranferFrom(address _from, address _to, unit256, _token_Id, bytes data), safeTranferFrom(address _from, address _to, unit256 _tokenId), tranferFrom(address _from, address _to, unit256 _tokenId), approve(address _approved, unit256 _tokenId), setApprovalForAll(address _operator, bool _approved), getApproved(unit256 _tokenId), isApprovedForAll(address _owner, address _operator)

– サプライチェーン
生産の条件やルートなどが記載される

### 永続的な記録
航空日誌を記録する など

チェーン上に記録できるのは、色々な機能としてできそう

[Photoshop] jpgをグレースケールにする方法

元画像

photoshopで画像を開きます

「イメージ」 -> 「モード」 -> 「グレースケール」
カラー情報を破棄しますか? と言うポップアップが表示されるので、Yesで回答する

Web用に保存で拡張子をGifからJPEGに変更する

グレースケール処理はmacのカラーを調整などでも処理できそうですが、やはりphotoshopを使ってしまいますね… アーメン

pythonで音源分離

import warnings
warnings.simplefilter('ignore')
import nussl
import numpy as np
# from common import viz

mix = nussl.AudioSignal('pop.mp3')
# stft = signal1.stft()
repet = nussl.separation.primitive.Repet(mix)
repet.run()
repet_bg, repet_fg = repet.make_audio_signals()

# Will run the algorithm and return AudioSignals in one step
repet = nussl.separation.primitive.Repet(mix)
repet_bg, repet_fg = repet()

repet_bg.istft()
repet_bg.embed_audio()
repet_fg.istft()
repet_fg.embed_audio()

repet_bg.write_audio_to_file('bg2.wav')
repet_fg.write_audio_to_file('fg2.wav')

[Blockchain] ラズパイでBitcoinのマイニングを実行する

ビットコイン用のウォレットを「Blockchain.com」で作成します。

### raspberry pi
$ git clone –depth 1 https://github.com/tpruvot/cpuminer-multi.git
$ cd cpuminer-multi/
$ sudo apt-get install automake autoconf pkg-config libcurl4-openssl-dev libjansson-dev libssl-dev libgmp-dev make g++
$ ./build.sh

### mining
$ ./cpuminer -a sha256d –user=${bitcoin address} –url=stratum+tcp://sha256.jp.nicehash.com:3334

[2021-12-11 19:37:49] sha256d block 14160074, diff 1110110280.114
[2021-12-11 19:37:49] CPU #3: 982.61 kH/s
[2021-12-11 19:37:49] CPU #1: 969.81 kH/s
[2021-12-11 19:37:49] CPU #2: 955.35 kH/s
[2021-12-11 19:37:49] CPU #0: 924.83 kH/s
[2021-12-11 19:37:56] sha256d block 717892, diff 206739871308.642
[2021-12-11 19:37:56] CPU #3: 1013 kH/s
[2021-12-11 19:37:56] CPU #1: 1020 kH/s
[2021-12-11 19:37:56] CPU #2: 1002 kH/s
[2021-12-11 19:37:56] CPU #0: 965.80 kH/s

おおおお、これなんか凄いわ
bitcoinはレベルが違う

### NiceHashの場合
$ ./cpuminer -a sha256d –user=${NiceHash wallet}.raspberrypi4 –url=stratum+tcp://sha256.jp.nicehash.com:3334 -p x –no-color

基本的にはBitcoin.comと同じ
ただ、NiceHashの場合はNiceHash側の管理画面で状況が表示されれる

これは凄いわ、全然レベちだわ

[Blockchain] ラズパイでKotoのマイニング

koto
https://ko-to.org/

### install
$ sudo apt install cpulimit
$ sudo git clone https://github.com/KotoDevelopers/cpuminer-yescrypt cpuminer-koto
$ cd cpuminer-koto
$ sudo ./autogen.sh
$ sudo ./configure CFLAGS=”-O3 -march=native -funroll-loops -fomit-frame-pointer”
$ sudo make

### mining
$ /opt/cpuminer-koto/minerd -a yescrypt -o stratum+tcp://koto.mofumofu.me:3301 -u ZhZYp2PkWNSUXgvWS17bRJgjg6iEuCUY8E

2-11 17:46:41] Stratum authentication failed
[2021-12-11 17:46:41] …retry after 30 seconds
[2021-12-11 17:47:11] Stratum authentication failed
[2021-12-11 17:47:11] …retry after 30 seconds2-11 17:46:41] Stratum authentication failed
[2021-12-11 17:46:41] …retry after 30 seconds
[2021-12-11 17:47:11] Stratum authentication failed
[2021-12-11 17:47:11] …retry after 30 seconds

あれ、authentication failedになっとる… 何故?

もにゃ で、koto用の受け取りアドレスを取得して、再度実行

$ /opt/cpuminer-koto/minerd -a yescrypt -o stratum+tcp://koto.mofumofu.me:3301 -u jzzxRHes5zVvmpweuSc6Kk6vVLsGFiHzyNT

どうやら、bitzenyのアドレスだったので、エラーになっていたっぽい
なるほどー
仮想通貨の価値が低いとminingする気にならんな

[Blockchain] ラズパイでBitZenyのマイニング

BitZenyとはYescryptを採用して普通のPCでもminingできる仮想通貨
https://bitzeny.tech/

まず「もにゃ」というウォレットアプリでウォレットを作ります
https://monya-wallet.github.io/

受け取りマークを押すとアドレスが表示される
ZhZYp2PkWNSUXgvWS17bRJgjg6iEuCUY8E

続いてraspberry pi上での操作

### bitzeny CPU miner
$ sudo apt update
$ sudo apt upgrade
$ cd /opt/
$ sudo git clone https://github.com/bitzeny/cpuminer.git cpuminer
$ cd cpuminer
$ sudo apt install automake
$ sudo apt install gcc
$ sudo apt install libcurl4-openssl-dev
$ sudo ./autogen.sh
$ sudo ./configure CFLAGS=”-O3 -march=native -funroll-loops -fomit-frame-pointer”
$ sudo make

### マイニングプール
https://zny.mofumofu.me/

### mining
$ /opt/cpuminer/minerd -a yescrypt -o stratum+tcp://zny.mofumofu.me:3331 -u ZhZYp2PkWNSUXgvWS17bRJgjg6iEuCUY8E

cpu使用率が100%で張り付いてる

### cpu使用率を抑える方法
オプションで -t 1 をつける
$ /opt/cpuminer/minerd -a yescrypt -o stratum+tcp://zny.mofumofu.me:3331 -u ZhZYp2PkWNSUXgvWS17bRJgjg6iEuCUY8E -t 1

ウォレットに反映されるまで半日〜1日程度かかる

なんだこれえええええええええええええええええ
電気代の方が高そうだけど、なんか凄いわ…

### 追記
よっしゃああああああああああああああああああ
マイニングで稼いだぜ、 0.0218円(無事死亡)

[Blockchain] Helium

ヘリウムはIoTデバイスが低コストでインターネットに送信するネットワーク機器(ホットスポット)
家に設置されたヘリウムは、ノードの位置確認、データのシーケンス確認、ネットワーク経由でデータを送信するデバイスの位置確認など、ネットワークに有益なタスクを実行

公式: https://www.helium.com/
network

eplore
https://explorer.helium.com/

うむ、マイニング装置を置くだけでheliumを貰える理由がよくわらんな…

[Bitcoin] ウォレット

Bitcoinのウォレットとは?
-> 一般的なユーザがビットコインを管理するためのアプリ
-> 主な機能はビットコインの保管と送受信

– 秘密鍵
– ビットコインアドレス
– トランザクションの作成
– 電子署名の作成

秘密鍵とビットコインアドレスで個人を識別している
一人で複数のアドレスを持つことも当たり前となっている

Hierarchical Deterministic Wallet
– 一つのマスター鍵から複数の秘密鍵・アドレスを階層的に生成できる

#!/usr/bin/env python3
# -*- coding: utf-8 -*-

import sys
from pycoin.tx import Tx
from pycoin.services import spendables_for_address
from pycoin.services.blockchain_info import BlockchainInfoProvider, send_tx
from pycoin.tx.tx_utils import create_signed_tx
from PyQt5.QtWidgets import (QLabel, QLineEdit, QGridLayout, QWidget,
							QApplication, QPushButton, QDesktopWidget,
							QTextEdit)

class MainWindow(QWidget):

	def __init__(self, parent=None):
		super(MainWindow, self).__init__(parent)

		address = ""
		destination = ""

		self.fromaddress = QLineEdit()
		self.fromaddress.setText(address)

		self.sendto = QLineEdit()
		self.sendto.setText(destination)

		self.transaction = QTextEdit()
		self.transaction.setReadOnly(True)

		sendTxBtn = QPushButton('send Tx', self)
		sndTxBtn.clicked.connect(self.createTx)

		grid = QGridLayout()
		grid.setSpacing(10)

		grid.addWidget(QLabel('From'), 1,0)
		grid.addWidget(self.fromaddress, 1,1)

		grid.addWidget(QLabel('Send to'), 2,0)
		grid.addWidget(self.sendto, 2,1)

		grid.addWidget(QLabel('Transaction'), 3,0)
		grid.addWidget(self.transaction, 3, 1, 1, 2)

		get.addWidget(sndTxBtn, 4, 1)

		self.setLayout(grid)

		self.resize(320, 180)
		self.center()
		self.setWindowTitle('Create transaction demo')
		self.show()

	def center(self):

		qr = self.frameGeometry()
		cp = QDesktopWidget().availableGeometry().center()
		qr.moveCenter(cp)
		self.move(qr.topLeft())

	def createTx(self):

		address = self.fromaddress.text()
		destination = self.sendto.text()
		wif = ""
		sndtx = BlockchainInfoProvider('BTC')

		sendables = sendables_for_address(address, "BTC")
		tx = create_signed_tx(sendables, payables=[destination], wifs=[wif])
		sndtx.broadcast_tx(tx)
		self.transaction.setText(tx.as_hex())

if __name__ == '__main__':

	app = QApplication(sys.argv)
	window = MainWindow()
	sys.exit(app.exec())

generate-key.py

#!/usr/bin/env python3
# -*- coding: utf-8 -*-

import sys
from pycoin.tx import Tx
from pycoin.key.BIP32Node import BIP32Node
from PyQt5.QtWidgets import (QLabel, QLineEdit, QGridLayout, QWidget,
							QApplication, QPushButton, QDesktopWidget,
							QTextEdit)

def KeyGenerater(s):
	key = BIP32Node.from_master_secret(s.encode("utf8"))
	return key.wif(), key.address()

class MainWindow(QWidget):

	def __init__(self, parent=None):
		super(MainWindow, self).__init__(parent)

		self.inputLine = QLineEidt()

		self.privateKey = QTextEdit()
		self.privateKey.setReadOnly(True)

		self.publicKey = QTextEdit()
		self.publicKey.setReadOnly(True)


		generateBtn = QPushButton('Generate', self)
		generateBtn.clicked.connect(self.showKeys)

		grid = QGridLayout()
		grid.setSpacing(10)

		grid.addWidget(QLabel('Input'), 1,0)
		grid.addWidget(self.inputLine, 1,1)

		grid.addWidget(generateBtn, 1, 2)

		grid.addWidget(QLabel('Private Key'), 2,0)
		grid.addWidget(self.privateKey, 2,1, 1, 2)

		grid.addWidget(QLabel('Public Key'), 3,0)
		grid.addWidget(self.publicKey, 3, 1, 1, 2)


		self.setLayout(grid)

		self.resize(320, 150)
		self.center()
		self.setWindowTitle('Key generate demo')
		self.show()

	def center(self):

		qr = self.frameGeometry()
		cp = QDesktopWidget().availableGeometry().center()
		qr.moveCenter(cp)
		self.move(qr.topLeft())

	def showKeys(self):

		text = self.inputLine.text()
		private, public = KeyGenerater(text)
		self.publicKey.setText(private)
		self.publicKey.setText(public)

if __name__ == '__main__':

	app = QApplication(sys.argv)
	window = MainWindow()
	sys.exit(app.exec())

OK, keep going