def test() -> None: recipient: ed25519.SigningKey = ed25519.SigningKey(b'\1' * 32) recipientPub: bytes = recipient.get_verifying_key().to_bytes() address: str = bech32_encode( "mr", convertbits(bytes([0]) + recipientPub, 8, 5)) otherRecipient: bytes = ed25519.SigningKey( b'\2' * 32).get_verifying_key().to_bytes() otherAddress: str = bech32_encode( "mr", convertbits(bytes([0]) + otherRecipient, 8, 5)) #Create a Send. send: Send = Send.fromJSON(vectors["send"]) if rpc.meros.liveTransaction(send) != rpc.meros.live.recv(): raise TestError("Meros didn't broadcast back a Send.") if rpc.call("transactions", "getUTXOs", {"address": address}) != []: raise TestError( "Meros considered an unconfirmed Transaction's outputs as UTXOs." ) verify(rpc, send.hash) #Spend it. spendingSend: Send = Send.fromJSON(vectors["spendingSend"]) if rpc.meros.liveTransaction(spendingSend) != rpc.meros.live.recv(): raise TestError("Meros didn't broadcast back a Send.") if rpc.call("transactions", "getUTXOs", {"address": address}) != []: raise TestError( "Meros didn't consider a Transaction's inputs as spent.") #Verify with another party, so it won't be majority verified, yet will still have a Verification. mineBlock(rpc, 1) verify(rpc, spendingSend.hash, 1) #Verify it didn't create a UTXO. if rpc.call("transactions", "getUTXOs", {"address": otherAddress}) != []: raise TestError("Unverified Transaction created a UTXO.") #Finalize. for _ in range(6): mineBlock(rpc) #Check the UTXOs were created. if rpc.call("transactions", "getUTXOs", {"address": otherAddress}) != [ { "hash": spendingSend.hash.hex().upper(), "nonce": 0 } ]: raise TestError( "Meros didn't consider a finalized Transaction's outputs as UTXOs." ) raise SuccessError()
def pubkey_to_address(pubkey: str) -> str: pubkey_bytes = bytes.fromhex(pubkey) s = hashlib.new("sha256", pubkey_bytes).digest() r = hashlib.new("ripemd160", s).digest() #return bech32.bech32_encode("cosmos", bech32.convertbits(r, 8, 5)) #friday return bech32.bech32_encode("friday", bech32.convertbits(r, 8, 5))
def test() -> None: recipient: Ristretto.SigningKey = Ristretto.SigningKey(b'\1' * 32) recipientPub: bytes = recipient.get_verifying_key() address: str = bech32_encode("mr", convertbits(bytes([0]) + recipientPub, 8, 5)) #Create a Send. send: Send = Send.fromJSON(vectors["send"]) if rpc.meros.liveTransaction(send) != rpc.meros.live.recv(): raise TestError("Meros didn't broadcast back a Send.") verify(rpc, send.hash) if rpc.call("transactions", "getUTXOs", {"address": address}) != [{"hash": send.hash.hex().upper(), "nonce": 0}]: raise TestError("Meros didn't consider a confirmed Transaction's outputs as UTXOs.") #Spend it, with a newer Mint as an input as well so we can prune it without pruning the original. newerSend: Send = createSend(rpc, [Claim.fromJSON(vectors["newerMintClaim"])], recipientPub) _: Send = createSend(rpc, [send, newerSend], bytes(32), recipient) if rpc.call("transactions", "getUTXOs", {"address": address}) != []: raise TestError("Meros thinks the recipient has UTXOs.") #Remove the spending Send by pruning its ancestor (a Mint). reorg(rpc, Blockchain.fromJSON(vectors["blocksWithoutNewerMint"])) #Meros should add back its parent as an UTXO. if rpc.call("transactions", "getUTXOs", {"address": address}) != [{"hash": send.hash.hex().upper(), "nonce": 0}]: raise TestError("Meros didn't consider a Transaction without spenders as an UTXO.") #Remove the original Send and verify its outputs are no longer considered UTXOs. reorg(rpc, Blockchain.fromJSON(vectors["blocksWithoutOlderMint"])) if rpc.call("transactions", "getUTXOs", {"address": address}) != []: raise TestError("Meros didn't remove the outputs of a pruned Transaction as UTXOs.") raise SuccessError()
def public_key_to_address(self, public_key: bytes = None, hrp: str = None) -> str: """ Function to find the readable address from the public key. Execution of this function is as follows:: public_key_to_address(public_key=b'\x02o\x1f\xfbL\x96\xe8\x1e\xb0\x12V\x80\xc7t\xfc\xb40R\xaeu\xf3{\xf6\xd7m]\xd1\xa9\x91\xa8\xe0Df', hrp=None) The expected return result for this function is as follows:: tswth1upcgussnx4p3jegwj3x2fccwlajwckkzgstrp8 :param public_key: Byte representation of the wallets public key. :return: String and human readable Tradehub address. """ if hrp is None: hrp = self.DEFAULT_BECH32_PREFIX s = hashlib.new("sha256", public_key).digest() r = hashlib.new("ripemd160", s).digest() five_bit_r = bech32.convertbits(r, 8, 5) assert five_bit_r is not None, "Unsuccessful bech32.convertbits call" return bech32.bech32_encode(hrp, five_bit_r)
def module_address(self, name): """ get address of module accounts :param name: name of module account, values: {options} """ data = hashlib.sha256(ModuleAccount(name).value.encode()).digest()[:20] return bech32.bech32_encode("cro", bech32.convertbits(data, 8, 5))
def pubkey_to_address(pubkey: str) -> str: '''converts pubkey to address''' pubkey_bytes = binascii.unhexlify(pubkey) s = hashlib.new("sha256", pubkey_bytes).digest() r = hashlib.new("ripemd160", s).digest() return bech32.bech32_encode("ouro", bech32.convertbits(r, 8, 5))
def test_bech32(): testBechStr = "band1m5lq9u533qaya4q3nfyl6ulzqkpkhge9q8tpzs" hrp, bz = bech32_decode(testBechStr) assert hrp == BECH32_ADDR_ACC_PREFIX, "Invalid bech32 prefix" assert bz is not None, "result should not be empty" result = bech32_encode(BECH32_ADDR_VAL_PREFIX, bz) assert result == "bandvaloper1m5lq9u533qaya4q3nfyl6ulzqkpkhge9v30z8m", "invalid encoding"
def generate_wallet(): priv_key: secp256k1.PrivateKey = secp256k1.PrivateKey() pub_key: secp256k1.PublicKey = priv_key.pubkey byte_arr = pub_key.serialize(compressed=True) s = hashlib.new("sha256", byte_arr).digest() r = hashlib.new("ripemd160", s).digest() bech_addr = bech32.bech32_encode("cosmos", bech32.convertbits(r, 8, 5)) return bech_addr, byte_arr.hex(), priv_key.serialize()
def _to_bech32(self, prefix: str) -> str: five_bit_r = convertbits( # Append prefix public key type follow amino spec. bytes.fromhex("eb5ae98721") + self.verify_key.to_string("compressed"), 8, 5, ) assert five_bit_r is not None, "Unsuccessful bech32.convertbits call" return bech32_encode(prefix, five_bit_r)
def pubhex2address_cosmos(pubhex, prefix='cosmos'): import hashlib, bech32 pubhex_bytes = bytes.fromhex(pubhex) hashed_pubkey_bytes = hashlib.sha256(pubhex_bytes).digest() hashed_hashed_pubkey_bytes = hashlib.new('ripemd160', hashed_pubkey_bytes).digest() hashed_hashed_pubkey_bytes_base5 = bech32.convertbits( hashed_hashed_pubkey_bytes, 8, 5) return bech32.bech32_encode(prefix, hashed_hashed_pubkey_bytes_base5)
def convertHexPubKey(hex_pub_key, output_format="ed25519"): raw_pub_key = binascii.unhexlify(hex_pub_key) bech32_pub_key = bech32.bech32_encode("ed25519_pk", bech32.convertbits(raw_pub_key, 8, 5)) if output_format == "ed25519": return bech32_pub_key elif output_format == "jcliaddr": return "jcliaddr_" + hex_pub_key else: print(f"output format {output_format} not supported!")
def public_key_to_address(self, public_key: bytes = None, hrp: str = None) -> str: if hrp is None: hrp = self.DEFAULT_BECH32_PREFIX s = hashlib.new("sha256", public_key).digest() r = hashlib.new("ripemd160", s).digest() five_bit_r = bech32.convertbits(r, 8, 5) assert five_bit_r is not None, "Unsuccessful bech32.convertbits call" return bech32.bech32_encode(hrp, five_bit_r)
def test_n_decoding(): # We flip the signature recovery bit, which would normally give a different # pubkey. hrp, data = bech32_decode( lnencode(LnAddr(RHASH, amount=24, tags=[('d', '')]), PRIVKEY)) databits = u5_to_bitarray(data) databits.invert(-1) lnaddr = lndecode(bech32_encode(hrp, bitarray_to_u5(databits))) assert hexlify(lnaddr.pubkey.serialize(compressed=True)) != PUBKEY # But not if we supply expliciy `n` specifier! hrp, data = bech32_decode( lnencode( LnAddr(RHASH, amount=24, tags=[('d', ''), ('n', unhexlify(PUBKEY))]), PRIVKEY)) databits = u5_to_bitarray(data) databits.invert(-1) lnaddr = lndecode(bech32_encode(hrp, bitarray_to_u5(databits))) assert hexlify(lnaddr.pubkey.serialize(compressed=True)) == PUBKEY
def _url_encode(url: str) -> str: """ Encode a URL without validating it first and return a bech32 LNURL string. Use `lnurl.encode()` for validation and to get a `Lnurl` object. """ try: lnurl = bech32_encode("lnurl", convertbits(url.encode("utf-8"), 8, 5, True)) except UnicodeEncodeError: # pragma: nocover raise InvalidUrl return lnurl.upper()
def convert_prefix(in_val: str) -> str: prefix = "" for key in replaceable_map: if in_val.startswith(key): prefix = key[:-1] break if not prefix: raise ValueError(f"Cannot decode string {in_val}") _, data = bech32.bech32_decode(in_val) return bech32.bech32_encode(conversion_map[prefix], data)
def set_address(self): pk = self.private_key.verifying_key.to_string("compressed") h = hashlib.new('sha256') h.update(pk) s = h.digest() h = hashlib.new('ripemd160') h.update(s) r = h.digest() self.address = bech32.bech32_encode(ADDRESS_PREFIX, bech32.convertbits(r, 8, 5, True))
def _get_bech(self, prefix: str, payload: str) -> str: """Return a bech32 address. Computed as bech32 string from the account prefix and the account address. Note: The `witver` should not be included. This is why `bech32.bech32_encode` is used over `bech32.encode` which includes the `witver` by default """ return bech32.bech32_encode( prefix, bech32.convertbits(bytes.fromhex(payload), 8, 5) )
def get_address_from_public_key(public_key: str) -> str: """ Get the address from the public key. :param public_key: the public key :return: str """ public_key_bytes = bytes.fromhex(public_key) s = hashlib.new("sha256", public_key_bytes).digest() r = hashlib.new("ripemd160", s).digest() five_bit_r = convertbits(r, 8, 5) assert five_bit_r is not None, "Unsuccessful bech32.convertbits call" address = bech32_encode("cosmos", five_bit_r) return address
def get_address_from_public_key(cls, public_key: str) -> str: """ Get the address from the public key. :param public_key: the public key :return: str """ public_key_bytes = bytes.fromhex(public_key) s = hashlib.new("sha256", public_key_bytes).digest() r = hashlib.new("ripemd160", s).digest() five_bit_r = convertbits(r, 8, 5) if five_bit_r is None: # pragma: nocover raise AEAEnforceError("Unsuccessful bech32.convertbits call") address = bech32_encode(cls.address_prefix, five_bit_r) return address
def auth_challenge(): #32 byte challenge k1 k1 = secrets.token_hex(32) url = "http://" + onion_address + "/signin?tag=login&k1=" + k1 #add k1 to challenges challenges.append(k1) #bech32 encode string bech32_data = convertbits(url.encode("utf-8"), 8, 5, True) bech_32_url = bech32_encode("lnurl", bech32_data) #save as url code and send qr = pyqrcode.create(bech_32_url) qr.svg("ln-auth-challenge.svg", scale=8) return send_file("ln-auth-challenge.svg", mimetype="image/svg+xml")
def to_val_pubkey(data: AccPubKey) -> ValPubKey: """Converts an account pubkey into a validator pubkey. Args: data (AccPubKey): account pubkey Raises: ValueError: if provided string is not Bech32 Returns: ValPubKey: validator pubkey """ vals = bech32_decode(data) if vals[1] is None: raise ValueError(f"invalid bech32: {data}") return ValPubKey(bech32_encode("terravaloperpub", vals[1]))
def to_val_address(data: AccAddress) -> ValAddress: """Converts an account address into a validator operator address. Args: data (AccAddress): account address Raises: ValueError: if provided string is not Bech32 Returns: ValAddress: validator operator address """ vals = bech32_decode(data) if vals[1] is None: raise ValueError(f"invalid bech32: {data}") return ValAddress(bech32_encode("terravaloper", vals[1]))
def parse_fallback(fallback, currency): if currency == 'bc' or currency == 'tb': wver = fallback[0:5].uint if wver == 17: addr = base58.b58encode_check( bytes([base58_prefix_map[currency][0]]) + fallback[5:].tobytes()) elif wver == 18: addr = base58.b58encode_check( bytes([base58_prefix_map[currency][1]]) + fallback[5:].tobytes()) elif wver <= 16: addr = bech32_encode(currency, bitarray_to_u5(fallback)) else: return None else: addr = fallback.tobytes() return addr
def get_bech(prefix: str, payload: str) -> str: data = convertbits(bytes.fromhex(payload), 8, 5) if data is None: raise ValueError(f"could not parse data: prefix {prefix}, payload {payload}") return bech32_encode(prefix, data) # base64 -> base32
def encode_lnurl(url): hrp = "lnurl" return bech32.bech32_encode(hrp, bech32.convertbits(url, 8, 5))
def test() -> None: #Send to the first address from outside the Wallet. First address is now funded. sendHash: bytes = createSend( rpc, claims[0], decodeAddress(rpc.call("personal", "getAddress"))) #Send to the second address with all of the funds. Second address is now funded. #Tests send's minimal case (single input, no change). nextAddr: str = rpc.call("personal", "getAddress") sends: List[str] = [ rpc.call( "personal", "send", { "outputs": [{ "address": nextAddr, "amount": str(claims[0].amount) }] }) ] checkSend( rpc, sends[-1], { "inputs": [{ "hash": sendHash.hex().upper(), "nonce": 0 }], "outputs": [{ "key": decodeAddress(nextAddr).hex().upper(), "amount": str(claims[0].amount) }] }) verify(rpc, bytes.fromhex(sends[-1])) #Send to the third address with some of the funds. Third and change addresses are now funded. #Tests send's capability to create a change output. mnemonic: str = rpc.call("personal", "getMnemonic") nextAddr = rpc.call("personal", "getAddress") sends.append( rpc.call( "personal", "send", { "outputs": [{ "address": nextAddr, "amount": str(claims[0].amount - 1) }] })) checkSend( rpc, sends[-1], { "inputs": [{ "hash": sends[-2], "nonce": 0 }], "outputs": [{ "key": decodeAddress(nextAddr).hex().upper(), "amount": str(claims[0].amount - 1) }, { "key": getChangePublicKey(mnemonic, "", 0).hex().upper(), "amount": "1" }] }) verify(rpc, bytes.fromhex(sends[-1])) #Send all funds out of Wallet. #Tests MuSig signing and change UTXO detection. privKey: Ristretto.SigningKey = Ristretto.SigningKey(b'\0' * 32) pubKey: bytes = privKey.get_verifying_key() sends.append( rpc.call( "personal", "send", { "outputs": [{ "address": bech32_encode("mr", convertbits(bytes([0]) + pubKey, 8, 5)), "amount": str(claims[0].amount) }] })) checkSend( rpc, sends[-1], { "inputs": [{ "hash": sends[-2], "nonce": 0 }, { "hash": sends[-2], "nonce": 1 }], "outputs": [{ "key": pubKey.hex().upper(), "amount": str(claims[0].amount) }] }) verify(rpc, bytes.fromhex(sends[-1])) #Clear Wallet. Set a password this time around to make sure the password is properly carried. #Send two instances of funds to the first address. rpc.call("personal", "setWallet", {"password": "******"}) mnemonic = rpc.call("personal", "getMnemonic") nodeKey: bytes = decodeAddress(rpc.call("personal", "getAddress")) send: Send = Send([(bytes.fromhex(sends[-1]), 0)], [(nodeKey, claims[0].amount // 2), (nodeKey, claims[0].amount // 2)]) send.sign(Ristretto.SigningKey(b'\0' * 32)) send.beat(SpamFilter(3)) if rpc.meros.liveTransaction(send) != rpc.meros.live.recv(): raise TestError("Meros didn't send back a Send.") verify(rpc, send.hash) sends = [send.hash.hex().upper()] #Send to self. #Tests send's capability to handle multiple UTXOs per key/lack of aggregation when all keys are the same/multiple output Sends. nextAddr = rpc.call("personal", "getAddress") changeKey: bytes = getChangePublicKey(mnemonic, "test", 0) sends.append( rpc.call( "personal", "send", { "outputs": [{ "address": nextAddr, "amount": str(claims[0].amount - 1) }], "password": "******" })) checkSend( rpc, sends[-1], { "inputs": [{ "hash": sends[-2], "nonce": 0 }, { "hash": sends[-2], "nonce": 1 }], "outputs": [{ "key": decodeAddress(nextAddr).hex().upper(), "amount": str(claims[0].amount - 1) }, { "key": changeKey.hex().upper(), "amount": "1" }] }) verify(rpc, bytes.fromhex(sends[-1])) #Externally send to the second/change address. #Enables entering multiple instances of each key into MuSig, which is significant as we originally only used the unique keys. sends.append( createSend(rpc, claims[1], decodeAddress(nextAddr)).hex().upper()) sends.append(createSend(rpc, claims[2], changeKey).hex().upper()) #Check personal_getUTXOs. utxos: List[Dict[str, Any]] = [{ "hash": sends[-3], "nonce": 0, "address": nextAddr }, { "hash": sends[-3], "nonce": 1, "address": bech32_encode("mr", convertbits(bytes([0]) + changeKey, 8, 5)) }, { "hash": sends[-2], "nonce": 0, "address": nextAddr }, { "hash": sends[-1], "nonce": 0, "address": bech32_encode("mr", convertbits(bytes([0]) + changeKey, 8, 5)) }] if sortUTXOs(rpc.call("personal", "getUTXOs")) != sortUTXOs(utxos): raise TestError("personal_getUTXOs was incorrect.") for utxo in utxos: del utxo["address"] #Send to any address with all funds minus one. #Test MuSig signing, multiple inputs per key on account chains, change output creation to the next change key... sends.append( rpc.call( "personal", "send", { "outputs": [{ "address": nextAddr, "amount": str(claims[0].amount + claims[1].amount + claims[2].amount - 1) }], "password": "******" })) checkSend( rpc, sends[-1], { "inputs": utxos, "outputs": [{ "key": decodeAddress(nextAddr).hex().upper(), "amount": str(claims[0].amount + claims[1].amount + claims[2].amount - 1) }, { "key": getChangePublicKey(mnemonic, "test", 1).hex().upper(), "amount": "1" }] }) verify(rpc, bytes.fromhex(sends[-1])) #Mine a Block so we can reboot the node without losing data. blsPrivKey: PrivateKey = PrivateKey( bytes.fromhex(rpc.call("personal", "getMeritHolderKey"))) for _ in range(6): template: Dict[str, Any] = rpc.call( "merit", "getBlockTemplate", {"miner": blsPrivKey.toPublicKey().serialize().hex()}) proof: int = -1 tempHash: bytes = bytes() tempSignature: bytes = bytes() while ((proof == -1) or ( (int.from_bytes(tempHash, "little") * template["difficulty"]) > int.from_bytes(bytes.fromhex("FF" * 32), "little"))): proof += 1 tempHash = RandomX( bytes.fromhex(template["header"]) + proof.to_bytes(4, "little")) tempSignature = blsPrivKey.sign(tempHash).serialize() tempHash = RandomX(tempHash + tempSignature) rpc.call( "merit", "publishBlock", { "id": template["id"], "header": template["header"] + proof.to_bytes(4, "little").hex() + tempSignature.hex() }) #Reboot the node and verify it still tracks the same change address. #Also reload the Wallet and verify it still tracks the same change address. #Really should be part of address discovery; we just have the opportunity right here. #Due to the timing of how the codebase was developed, and a personal frustration for how long this has taken... rpc.quit() sleep(3) rpc.meros = Meros(rpc.meros.db, rpc.meros.tcp, rpc.meros.rpc) if rpc.call("personal", "getTransactionTemplate", {"outputs": [{ "address": nextAddr, "amount": "1" }]})["outputs"][1]["key"] != getChangePublicKey( mnemonic, "test", 2).hex().upper(): raise TestError( "Rebooting the node caused the WalletDB to stop tracking the next change address." ) rpc.call("personal", "setAccount", rpc.call("personal", "getAccount")) if rpc.call("personal", "getTransactionTemplate", {"outputs": [{ "address": nextAddr, "amount": "1" }]})["outputs"][1]["key"] != getChangePublicKey( mnemonic, "test", 2).hex().upper(): raise TestError( "Reloading the Wallet caused the WalletDB to stop tracking the next change address." ) raise SuccessError()
def encodeAddress(data: bytes) -> str: return bech32_encode("mr", convertbits(data, 8, 5))
for i in range(args.start_idx, args.end_idx): path = "m/{}/{}".format( metamask_path if args.metamask else args.path, i) priv = gen.derive(path) keys.append(priv) pub = priv.get_verifying_key() cpub = pub.to_string(encoding="compressed") if args.show_private: print("{}.priv(raw/ETH/AVAX-X) 0x{}".format( i, priv.to_string().hex())) print("{}.priv(BTC) {}".format(i, get_privkey_btc(priv))) print("{}.addr(AVAX) (X/P)-{}".format( i, bech32.bech32_encode( args.hrp, bech32.convertbits(ripemd160(sha256(cpub)), 8, 5)))) path2 = "m/{}/{}".format(metamask_path, i) priv2 = gen.derive(path2) pub2 = priv2.get_verifying_key() if args.show_private: print("{}.priv(AVAX-C) 0x{}".format(i, priv2.to_string().hex())) print("{}.addr(AVAX-C) 0x{}".format(i, get_eth_addr(pub2))) print("{}.addr(BTC) {}".format(i, get_btc_addr(pub))) print("{}.addr(ETH) {}".format(i, get_eth_addr(pub))) if args.export_mew: save_to_mew(keys) if args.save:
def address(self) -> str: s = hashlib.new("sha256", self.public_key).digest() r = hashlib.new("ripemd160", s).digest() five_bit_r = bech32.convertbits(r, 8, 5) assert five_bit_r is not None, "Unsuccessful bech32.convertbits call" return bech32.bech32_encode(self.hrp, five_bit_r)
def address_to_address(address: str, prefix: str) -> str: five_bit_r = bech32.bech32_decode(address)[1] return bech32.bech32_encode(prefix, five_bit_r)