def utxos(self): if self._outputs is None: import urllib.request import json url = network('utxo_url').format(address=self.address) req = urllib.request.Request(url) outputs = [] try: with urllib.request.urlopen(req) as resp: data = json.loads(resp.read().decode()) except HTTPError as e: resp = e.read().decode() if resp == 'No free outputs to spend': self._outputs = [] else: raise UpstreamError(resp) else: for item in data['unspent_outputs']: out = Output(value=item['value'], script=hex_to_bytes(item['script'])) out.parent_id = hex_to_bytes(item['tx_hash_big_endian']) out.tx_index = item['tx_output_n'] outputs.append(out) self._outputs = outputs return self._outputs
def test_encoding(self): raw_sig = hex_to_bytes('304402206878b5690514437a2342405029426cc2b25b4a03fc396fef845d656cf62bad2c022018610a8d37e3384245176ab49ddbdbe8da4133f661bf5ea7ad4e3d2b912d856f') sig = Signature.decode(raw_sig) self.assertEqual(sig.r, 47253809947851177065887724633329625063088643784040492056218945870752194997548) self.assertEqual(sig.s, 11026965355983493404719379810734327200902731292741433431270495068542334764399) self.assertEqual(sig.encode(), raw_sig) r = hex_to_int('316eb3cad8b66fcf1494a6e6f9542c3555addbf337f04b62bf4758483fdc881d') s = hex_to_int('bf46d26cef45d998a2cb5d2d0b8342d70973fa7c3c37ae72234696524b2bc812') sig_high_s = hex_to_bytes('30450220316eb3cad8b66fcf1494a6e6f9542c3555addbf337f04b62bf4758483fdc881d022100bf46d26cef45d998a2cb5d2d0b8342d70973fa7c3c37ae72234696524b2bc812') sig_low_s = hex_to_bytes('30440220316eb3cad8b66fcf1494a6e6f9542c3555addbf337f04b62bf4758483fdc881d022040b92d9310ba26675d34a2d2f47cbd27b13ae26a7310f1c99c8bc83a850a792f') sig_high = Signature(r, s, force_low_s=False) sig_low = Signature(r, s, force_low_s=True) self.assertEqual(sig_low.encode(), sig_low_s) self.assertEqual(sig_high.encode(), sig_high_s) self.assertEqual(sig_low, Signature.decode(sig_high_s)) self.assertEqual(sig_low, Signature.decode(sig_low_s)) sig = Signature(secrets.randbelow(CURVE.N), secrets.randbelow(CURVE.N)) self.assertEqual(sig, Signature.decode(sig.encode())) # Test padding sig = Signature(secrets.randbelow(10**8), secrets.randbelow(10**8)) self.assertEqual(sig, Signature.decode(sig.encode()))
def from_seed(cls, seed: Union[bytes, str], addresstype='P2PKH') -> 'Xprv': if isinstance(seed, str): seed = hex_to_bytes(seed) assert 16 <= len(seed) <= 64, 'Seed should be between 128 and 512 bits' I = hmac.new(key=b"Bitcoin seed", msg=seed, digestmod=hashlib.sha512).digest() I_L, I_R = I[:32], I[32:] if bytes_to_int(I_L) == 0 or bytes_to_int(I_L) > CURVE.N: raise KeyDerivationError key, code = PrivateKey(I_L), I_R return cls(key, code, addresstype=addresstype)
def get_address(script): """Extracts the address from a scriptPubkey""" script = hex_to_bytes(script) if isinstance(script, str) else script stype = get_type(script) if stype == TX.P2SH: data = script[2:22] version = network('scripthash') return hashed_payload_to_address(version + data) elif stype == TX.P2PKH: data = script[3:23] version = network('keyhash') return hashed_payload_to_address(version + data) elif stype in (TX.P2WSH, TX.P2WPKH): witver = version_byte(script) witprog = witness_program(script) return bech32.encode(network('hrp'), witver, witprog) elif stype == TX.P2PK: return "N/A" raise ValidationError(f"Unknown script type: {bytes_to_hex(script)}")
def get_type(script): """https://github.com/bitcoin/bitcoin/blob/5961b23898ee7c0af2626c46d5d70e80136578d3/src/script/script.cpp#L202""" script = hex_to_bytes(script) if isinstance(script, str) else script if script.startswith(OP.HASH160.byte + OP.PUSH20.byte) and script.endswith( OP.EQUAL.byte) and len(script) == 23: return TX.P2SH elif script.startswith(OP.DUP.byte + OP.HASH160.byte) and script.endswith( OP.EQUALVERIFY.byte + OP.CHECKSIG.byte) and len(script) == 25: return TX.P2PKH elif script.startswith(b'\x00' + OP.PUSH32.byte) and len(script) == 34: return TX.P2WSH elif script.startswith(b'\x00' + OP.PUSH20.byte) and len(script) == 22: return TX.P2WPKH elif script.startswith(OP.PUSH65.byte + b'\x04') and script.endswith( OP.CHECKSIG.byte) and len(script) == 67: # uncompressed PK return TX.P2PK elif script.startswith((b'\x21\x03', b'\x21\x02')) and script.endswith( OP.CHECKSIG.byte) and len(script) == 35: # compressed PK return TX.P2PK else: raise ScriptValidationError( f"Unknown script type: {bytes_to_hex(script)}")
def asm(script): """Turns a script into a symbolic representation""" if isinstance(script, str): script = hex_to_bytes(script) else: script = copy(script) def read(n): nonlocal script data = script[:n] assert data or n == 0, 'EOF' script = script[n:] return data results = [] while script: byte = bytes_to_int(read(1)) op = OP(byte) if byte in range(1, 76): results.append(bytes_to_hex(read(byte))) else: results.append(str(op)) return ' '.join(results)
def from_hex(cls, hexstring: str) -> 'PublicKey': return cls.decode(hex_to_bytes(hexstring))
def from_hex(cls, hexstring): return cls.deserialize(hex_to_bytes(hexstring))