[Bitcoin] Walletの概要

秘密鍵 => 公開鍵 => ビットコインウォレットの順番で作られる。
OpenSSLで秘密鍵、公開鍵を作る手順と一緒
ウォレットは、「秘密鍵」「公開鍵」を保持し、管理する

### ウォレットの鍵の管理手法
ランダムウォレット と HDウォレットがある

– ランダムウォレット
秘密鍵公開鍵を1:1の関係で生成し管理する
ただし、複数の秘密鍵を管理保持しなければならない

– HDウォレット(Hierarchy Deterministic)
シードと呼ばれる値から秘密鍵を生成し、階層構造を用いて管理する
シードがあれば、秘密鍵は複数管理する必要はない(管理コストが下がる)

乱数生成器 -> シード -> HMAC-SHA512 -> 親秘密鍵(256bit) + 親ChainCode(256bit) *子秘密鍵生成に使用

親秘密鍵 + 親ChainCode + index -> HMAC-SHA512 -> 子秘密鍵 + 子ChainCode

### パスフレーズ, BIP32, BIP44
パスフレーズとは、どの階層にどの鍵が存在するのかを一意に表したものでスラッシュ区切りで表現
BIP32の標準規格: m/a’/c/i
BIP44の標準規格: m / purpose’ / coin_type’ / account’ / change /

### HMAC-sha512
HMACは、暗号ハッシュ関数を使用して、メッセージ認証を行う仕組み

import hmac
import hashlib
key="asdf"
text="public text"
signature = hmac.new(bytearray(key, "ASCII"),bytearray(text, "ASCII"), hashlib.sha512).hexdigest()
print(signature)

$ python3 wallet.py
b83ed32cab16c05e43f0922cf5123f04d2278d4fa50e4b1edab5f0ce04e74d5900b91dec501efd96de4721313f56533b55c1fec837b92bebe6126df7838dcc6d

### bitcoinのlibraryを使う場合

from bitcoin import *
my_private_key = random_key()
print(my_private_key)
public_key = privtopub(my_private_key)
print(public_key)
wallet_address = pubtoaddr(public_key)
print(wallet_address)

秘密鍵 => 公開鍵 => ビットコインウォレットの順番で作る

$ python3 wallet.py
336a4393ccef96b9eedb78deff766a6289d6e47983b35ee58860dd65c1a8fb86
04ef2a745e5853cea83031dd5a49de1716642ae55b1d537d2407f52757580071d7475b61b4efa2fa355d50251a286850a8548f808440c8e3739aa8bf31660dfab3
1FegPWcNYxpVMRg8rT8NhWXkzWAuk6WX2A

ああああああああああ
もうやだあ

[Blockchain] Ubuntu20.04・OpenSSLで秘密鍵公開鍵の操作

$ openssl version
OpenSSL 1.1.1f 31 Mar 2020

### 秘密鍵の作成
$ openssl ecparam -genkey -name secp256k1 -out private.pem
// ecparamは楕円曲線暗号における楕円曲線パラメータに関するサブコマンド
$ cat private.pem
—–BEGIN EC PARAMETERS—–
BgUrgQQACg==
—–END EC PARAMETERS—–
—–BEGIN EC PRIVATE KEY—–
MHQCAQEEINB5OV0K2ggkM2a0bmVTcj7FioqK5TDI9NJAxgOUjcFOoAcGBSuBBAAK
oUQDQgAELnHK99GtgUL9F3Q5YSwYa5ZdI8uY0P5diBTZZN4Ld7feo13zqYO9oQm3
G1YHB2ITeG81+KridKnVOzDk0RwA7w==
—–END EC PRIVATE KEY—–

### 公開鍵の作成
$ openssl ec -in private.pem -pubout -out public.pem
// echは楕円曲線暗号に関するサブコマンド
read EC key
writing EC key
$ cat public.pem
—–BEGIN PUBLIC KEY—–
MFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAELnHK99GtgUL9F3Q5YSwYa5ZdI8uY0P5d
iBTZZN4Ld7feo13zqYO9oQm3G1YHB2ITeG81+KridKnVOzDk0RwA7w==
—–END PUBLIC KEY—–

### メッセージの作成、ハッシュ化
$ sha256sum test.txt | cut -c1-64 > hashed.txt
$ cat hashed.txt
d8aa344276524074fbfec2249bedb89a5ddccc9dc57504e92a9963f48bdf68d1

### verify
ハッシュ化した書類と秘密鍵でhashed.sigを作成し、公開鍵とhashed.sigで検証する
$ openssl dgst -SHA256 -sign private.pem hashed.txt > hashed.sig
// dgstはメッセージダイジェストを計算
$ ls
hashed.sig hashed.txt private.pem public.pem test.txt
$ openssl dgst -SHA256 -verify public.pem -signature hashed.sig hashed.txt
Verified OK

apostilleのことだね

[NEM/XEM] 独自トークンの発行

NEMのサイトに飛びます
https://discord.com/invite/xymcity

これはdiscordのチャットですね

Symbol
https://jp.symbolplatform.com/

Nemplatform wallet

Wallets


これか

import してログインする

namespace : 独自トークンを機能させるための場所
mosaic : トークの詳細設定(名称、初期供給量、小数点)

早速NEM Walletにnemを送ってみます。120NEMが必要ということなので、124NEM送る
NEMはBlock chainに比べて、blockが作られる時間が早い
https://explorer.nemtool.com/

すると、アカウントに124NEMが入っている!

### namespace
create namespaceでcapitalcoinとします
すると、100.15NEM引かれて、Dashboardでnamespaceが作られます

### Mosaics
namespaceが作られると、mosaicsの作成ができるようになります。
Mosaic name: hpscript
Description: Hpscript
Initial Supply: 100000000
Total Supply: 100000000

### Mosaicの送信
もにゃに送信できるらしいが、もにゃ側でエラーになる…

発行は簡単にできるが、使い方がイマイチやな

[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

[Bitcoin] マイニング

from hashlib import sha256
text = "ABC"
print(sha256(text.encode('ascii')).hexdigest())

$ python3 main.py
b5d4045c3f466fa91fe2cc6abe79232a1a57cdf104f7a26e716e0a1e2789df78

from hashlib import sha256
MAX_NONCE = 10000000000

def SHA256(text):
	return sha256(text.encode('ascii')).hexdigest()

def mine(block_number, transactions, previous_hash, prefix_zeros):
    prefix_str = '0'*prefix_zeros
    for nonce in range(MAX_NONCE):
        text = str(block_number) + transactions + previous_hash + str(nonce)
        new_hash = SHA256(text)
        if new_hash.startswith(prefix_str):
            print(f"Yay! Successfully mined bitcoins with nonce value:{nonce}")
            return new_hash

    raise BaseException(f"Couldn't find correct has after trying {MAX_NONCE} times")


if __name__ == '__main__':
	transactions='''
	Bob->Alice->20,
	Ken->Ryu->45
	'''
	difficulty=6
	new_hash = mine(5, transactions, '00000000000008a3a41b85b8b29ad444def299fee21793cd8b9e567eab02cd81', difficulty)
	print(new_hash)

bitcoin hardware
https://www.buybitcoinworldwide.com/mining/hardware/

bitcoin explore
https://www.blockchain.com/explorer
https://www.blockchain.com/btc/blocks?page=1

bitcoin block1
https://www.blockchain.com/btc/block/1

なるほど、前後の処理が知りたいのう

[Bitcoin] ブルームフィルター

軽量クライアントがフルノードに伝えるトランザクション
フルノードはブルームフィルターを介してトランザクションを取り扱い、通過するトランザクションに関しmerkleblockコマンドを送信する

アイテムがどの入れ物に入るかを判断するプロセス

from helper import hash256
bit_field_size=10
bit_field = [0] * bit_field_size
h = hash256(b'hello world')
bit = int.from_bytes(h, 'big') % bit_field_size
bit_field[bit] = 1
print(bit_field)

複数

from helper import hash256
bit_field_size=10
bit_field = [0] * bit_field_size
for item in (b'hello world', b'goodbye'):
	h = hash256(item)
	bit = int.from_bytes(h, 'big') % bit_field_size
	bit_field[bit] = 1
print(bit_field)

### 複数ハッシュ関数を使用するブルームフィルター

from helper import hash256, hash160
bit_field_size=10
bit_field = [0] * bit_field_size
for item in (b'hello world', b'goodbye'):
	for hash_function in (hash256, hash160):
		h = hash_function(item)
		bit = int.from_bytes(h, 'big') % bit_field_size
		bit_field[bit] = 1
print(bit_field)

### BIP0037ブルームフィルター
murmur3と呼ばれるハッシュ関数を使用する

from helper import murmur3
from bloomfilter import BIP37_CONSTANT
field_size = 2
num_functions = 2
tweak = 42
bit_field_size = field_size * 8
bit_field = [0] * bit_field_size
for phrase in (b'hello world', b'goodbye'):
	for i in range(num_functions):
		seed = i * BIP37_CONSTANT + tweak
		h = murmur3(phrase, seed=seed)
		bit = h % bit_field_size
		bit_field[bit] = 1
print(bit_field)

[0, 0, 0, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 0, 0, 0]

from bloomfilter import BloomFilter, BIP37_CONSTANT
from helper import bit_field_to_bytes, murmur3
field_size = 10
function_count = 5
tweak = 99
items = (b'Hello World', b'Goodbye!')
bit_field_size = field_size * 8
bit_field = [0] * bit_field_size
for item in items:
	for i in range(function_count):
		seed = i * BIP37_CONSTANT + tweak
		h = murmur3(item, seed=seed)
		bit = h % bit_field_size
		bit_field[bit] = 1
print(bit_field_to_bytes(bit_field).hex())

### ブルームフィルターの読み込み

	def filterload(self, flag=1):
		payload = encode_varint(self.size)
		payload += self.filter_bytes()
		payload += int_to_little_endian(self.function_count, 4)
		payload += int_to_little_endian(self.tweak, 4)
		payload += int_to_little_endian(flag, 1)
		return GenericMessage(b'filterload', payload)
class GetDataMessage:
	command = b'getdata'

	def __init__(self):
		self.data = []

	def add_data(self, data_type, identifier):
		self.data.append((data_type, identifier))

	def serialize(self):
		result = encode_varint(len(self.data))
		for data_type, identifier in self.data:
			result += int_to_little_endian(data_type, 4)
			result += identifier[::-1]
		return result
from bloomfilter import BloomFilter
from helper import decode_base58
from merkleblock import MerkleBlock
from network import FILTERED_BLOCK_DATA_TYPE, GetHeadersMessage, GetDataMessage, HeadersMessage, SimpleNode
from tx import Tx
last_block_hex = '00000000000538d5c2246336644f9a4956551afb44ba47278759ec55\
ea912e19'
address = 'mwJn1YPMq7y5F8J3LkC5Hxg9PHyZ5K4cFv'
h160 = decode_base58(address)
node = SimpleNode('testnet.programmingbitcoin.com', testnet=True, logging=False)
bf = BloomFilter(size=30, function_count=5, tweak=90210)
bf.add(h160)
node.handshake()
node.send(bf.filterload())
start_block = bytes.fromhex(last_block_hex)
getheaders = GetHeadersMessage(start_block=start_block)
node.send(getheaders)
headers = node.wait_for(HeadersMessage)
getdata = GetDataMessage()
for b in headers.blocks:
	if not b.check_pow():
		raise RuntimeError('proof of work is invalid')
	getdata.add_data(FILTERED_BLOCK_DATA_TYPE, b.hash())
node.send(getdata)
found = False
while not found:
	message = node.wait_for(MerkleBlock, Tx)
	if message.command == b'merkleblock':
		if not message.is_valid():
			raise RuntimeError('invalid merkle proof')
		else:
			for i, tx_out in enumerate(message.tx_outs):
				if tx_out.script_pubkey.address(testnet=True) == address:
					print('found: {}:{}'.format(message.id(), i))
					found = True
					break