def encode(self, compressed=False) -> bytes: # TODO Maybe easier Implementation if compressed: if self.y() & 1: # odd root return b'\x03' + int_to_bytes(self.x()).rjust(32, b'\x00') else: # even root return b'\x02' + int_to_bytes(self.x()).rjust(32, b'\x00') return b'\x04' + int_to_bytes(self.x()).rjust( 32, b'\x00') + int_to_bytes(self.y()).rjust(32, b'\x00')
def op_push(i: int) -> bytes: """ Push Operators https://en.bitcoin.it/wiki/Script#Constants """ if i < 0x4c: return int_to_bytes(i) elif i < 0xff: return b'\x4c' + int_to_bytes(i) elif i < 0xffff: return b'\x4d' + int_to_bytes(i) else: return b'\x4e' + int_to_bytes(i)
def child(self, i: int) -> 'XPub': hardened = i >= 1 << 31 if hardened: raise KeyDerivationError('Cannot derive a hardened key from an extended public key') I = hmac.new(key=self.code, msg=self.key_data() + int_to_bytes(i).rjust(4, b'\x00'), digestmod=hashlib.sha512).digest() I_L, I_R = I[:32], I[32:] key = PrivateKey(I_L).to_public().point + self.key.point ret_code = I_R path = self.path + f'/{i}' # TODO add point at infinity check return XPub( PublicKey(key, network=self.key.network), ret_code, depth=self.depth + 1, i=i, parent=self.fingerprint(), path=path, address_type=self.type.value )
def child(self, i) -> 'XPrv': hardened = i >= 1 << 31 if hardened: I = hmac.new( key=self.code, msg=self.key_data() + int_to_bytes(i).rjust(4, b'\x00'), digestmod=hashlib.sha512 ).digest() else: I = hmac.new( key=self.code, msg=self.key.to_public().encode(compressed=True) + int_to_bytes(i).rjust(4, b'\x00'), digestmod=hashlib.sha512 ).digest() I_L, I_R = bytes_to_int(I[:32]), I[32:] key = (I_L + self.key.int()) % DefaultCurve.order if I_L >= DefaultCurve.order or key == 0: return self.child(i + 1) ret_code = I_R if hardened: path = self.path + f'/{i - 2 ** 31}h' else: path = self.path + f'/{i}' private = PrivateKey.from_int(key) private.network = self.key.network return XPrv( key=private, code=ret_code, depth=self.depth + 1, i=i, parent=self.fingerprint(), path=path, address_type=self.type.value )
def from_binary(cls, b): return cls(int_to_bytes(int(b, 2)))
def from_int(cls, i): return cls(int_to_bytes(i))
def serialize(self): version = get_network_attr('extended_pub', self.key.network)[self.type] depth = int_to_bytes(self.depth) child = bytes(4) if self.is_master() else int_to_bytes(self.i).rjust(4, b'\x00') return version + depth + self.parent + child + self.code + self.key_data()
def witness_byte(witver: int) -> bytes: assert 0 <= witver <= 16, "Witness version must be between 0-16" return int_to_bytes(witver + 0x50 if witver > 0 else 0)