def __add__(self, other):
if self.prime != other.prime:
raise TypeError('Cannot add two numbers in different Fields')
num = (self.num + other.num) % self.prime
return self.__class__(num, self.prime)
Pythonのraise ValueError
関数などで例外を発生させたい場合にraiseを使用する。
raise 例外クラス(message):
def process_list(numbers):
for num in numbers:
try:
if num < 0:
raise ValueError("Negative numbers are not allowed.")
result = 100 / num
print(f"Result of division: {result}")
except ZeroDivisionError:
print("Error: Division by zero is not allowed.")
except ValueError as ve:
print(f"Error: {ve}")
except Exception as e:
print(f"Error occurred: {e}")
Pythonの__eq__メソッド
__eq__メソッド は等価の条件を定める
class Person:
def __init__(self, firstname, lastname, email):
self.firstname = firstname
self.lastname = lastname
self.email = email
def __eq__(self, other):
if other is None or not isinstance(other, Person): return False
return self.firstname == other.firstname and \
self.lastname == other.lastname and \
self.email == other.email
def __ne__(self, other):
return not self.__eq__(other)
mike = Person('Mike', 'Peter', 'mike@gmail.com')
peter = Person('Mike', 'Peter', 'mike@gmail.com')
print(mike)
print(peter)
print(mike == peter)
eqの他にも、lt, ne, le, gt, geなどがある。
class Item(object):
def __init__(self, price):
self.price = price
def __eq__(self, other):
if not isinstance(other, Item):
return NotImplemented
return self.price == other.price
def __lt__(self, other):
if not isinstance(other, Item):
return NotImplemented
return self.price < other.price
def __ne__(self, other):
return not self.__eq__(other)
def __le__(self, other):
return self.__lt__(other) or self.__eq__(other)
def __gt__(self, other):
return not self.__le__(other)
def __ge__(self, other):
return not self.__lt__(other)
Pythonの__rpr__メソッド
__str__, __repr__は特殊メソッドと呼ぶ
initのみの場合
class Person:
def __init__(self, name: str, age: int) -> None:
self.name = name
self.age = age
mike = Person('Mike', 20)
print(mike)
class Person:
def __init__(self, name: str, age: int) -> None:
self.name = name
self.age = age
mike = Person('Mike', 20)
print(f'name: {mike.name}, age: {mike.age}')
classの中に書く
class Person:
def __init__(self, name: str, age: int) -> None:
self.name = name
self.age = age
def __str__(self) -> str:
return f'name: {mike.name}, age: {mike.age}'
mike = Person('Mike', 20)
print(mike)
__repr__ は同じ値のオブジェクトを再生成できる文字列を定義。
class Person:
def __init__(self, name: str, age: int) -> None:
self.name = name
self.age = age
def __repr__(self) -> str:
return f'name: {mike.name}, age: {mike.age}'
mike = Person('Mike', 20)
print(repr(mike))
class Person:
def __init__(self, name: str, age: int) -> None:
self.name = name
self.age = age
def __repr__(self) -> str:
return f'name: {mike.name}, age: {mike.age}'
mike = Person('Mike', 20)
print(repr(mike))
有限体とは
位数が有限である体
四則演算が定義され閉じている有限集
整数の集合は無限の要素だが、有限体は要素が有限で、四則演算(足し算・引き算・掛け算・割り算)が閉じている
=> 閉じているとは、演算結果が、有理数でなくなるということがない
=> 演算を施した結果がふたたびもとの集合に属する
素数 P で割った余り
これ、初手でいきなりつまづくな…
python int.from_bytesでバイトから整数に
a = 128 print(a.to_bytes(2, 'big')) print(a.to_bytes(4, 'big')) print(int.from_bytes(b'\x00\x80', 'big')) print(int.from_bytes(b'\x00\x00\x00\x80', 'big'))
pythonとhmac-sha512
HMACは暗号ハッシュ関数を使用してメッセージ認証を行う仕組み
import hmac import hashlib key=b"secret2" text=b"foo bar" signature=hmac.new(key,text,hashlib.md5).hexdigest() print(signature)
b””としないと、エラーになる。
self._hmac = _hashopenssl.hmac_new(key, msg, digestmod=digestmod)
TypeError: Strings must be encoded before hashing
16進数と整数の変換
0xはその文字列が16進数であることを示す
print(format(0xabcd, 'x'))
print(hex(0xabcd))
print('%02x' % 0xabcd)
binasciiはバイト列に変換する
import binascii
print(binascii.unhexlify('abcd'))
print(str(binascii.hexlify(b'\xab\xcd'), 'utf-8'))
blockchain
import hashlib
class Block():
def __init__(self, data, prev_hash):
self.index = 0
self.nonce = 0
self.prev_hash = prev_hash
self.data = data
def blockhash(self):
blockheader = str(self.index) + str(self.prev_hash) + str(self.data) + str(self.nonce)
block_hash = hashlib.sha256(blockheader.encode()).hexdigest()
return block_hash
def __str__(self):
return "Block Hash: " + self.blockhash() + "\nPrevious Hash: " + self.prev_hash + "\nindex: " + str(self.index) + "\nData: " + str(self.data) + "\nNonce: " + str(self.nonce) + "\n--------------"
class Hashchain():
def __init__(self):
self.chain = ["0000000000000000000000000000000000000000000000000000000000000000"]
def add(self, hash):
self.chain.append(hash)
hashchain = Hashchain()
target = 0x777777 * 2**(8*(0x1e - 0x03))
for i in range(30):
block = Block("Block " + str(i+1), hashchain.chain[-1])
block.index = block.index + i + 1
for n in range(4294967296):
block.nonce = block.nonce + n
if int(block.blockhash(), 16) < target:
print(block)
hashchain.add(block.blockhash())
break
Proof of work
簡易的なhash計算
import hashlib
input_text = "satoshi"
for nonce in range(20):
input_data = input_text + str(nonce)
hash = hashlib.sha256(input_data.encode("UTF-8")).hexdigest()
print(input_data + " → " + hash)
ブロックヘッダのdifficulty bitsにハッシュ値の条件が書かれている
0x1e777777 のような形式で記述されている。
# difficulty_bits = 0x1e777777 # exponent = 0x1e # coefficient = 0x777777 target = 0x777777 * 2**(8*(0x1e - 0x03)) print(target) target_hex = hex(target)[2:].zfill(64) print(target_hex)
import hashlib
class Block():
def __init__(self, data, prev_hash):
self.index = 0
self.nonce = 0
self.prev_hash = prev_hash
self.data = data
def blockhash(self):
blockheader = str(self.index) + str(self.prev_hash) + str(self.data) + str(self.nonce)
block_hash = hashlib.sha256(blockheader.encode()).hexdigest()
return block_hash
def __str__(self):
return "Block Hash: " + self.blockhash() + "\nPrevious Hash: " + self.prev_hash + "\nindex: " + str(self.index) + "\nData: " + str(self.data) + "\nNonce: " + str(self.nonce) + "\n--------------"
class Hashchain():
def __init__(self):
self.chain = ["0000000000000000000000000000000000000000000000000000000000000000"]
def add(self, hash):
self.chain.append(hash)
hashchain = Hashchain()
target = 0x777777 * 2**(8*(0x1e - 0x03))
for i in range(30):
block = Block("Block " + str(i+1), hashchain.chain[-1])
block.index = block.index + i + 1
for n in range(4294967296):
block.nonce = block.nonce + n
if int(block.blockhash(), 16) < target:
print(block)
hashchain.add(block.blockhash())
break