Ejemplo n.º 1
0
def is_valid_substrate_address(
    chain: SubstrateChain,
    value: str,
) -> bool:
    """Validates a ss58 encoded substrate address for the given chain.

    Polkascan ss58 utils documentation:
    https://github.com/polkascan/py-substrate-interface/blob/master/substrateinterface/utils/ss58.py  # noqa: E501

    External Address Format (SS58) documentation:
    https://github.com/paritytech/substrate/wiki/External-Address-Format-(SS58)
    """
    if chain == SubstrateChain.KUSAMA:
        valid_ss58_format = 2
    else:
        raise AssertionError(f'Unexpected chain: {chain}')

    try:
        ss58_decode(
            address=value,
            valid_ss58_format=valid_ss58_format,
        )
    except ValueError:
        return False
    return True
Ejemplo n.º 2
0
    def test_decode_reserved_ss58_formats(self):
        with self.assertRaises(ValueError) as cm:
            ss58_decode('MGP3U1wqNhFofseKXU7B6FcZuLbvQvJFyin1EvQM65mBcNsY8')

        self.assertEqual('46 is a reserved SS58 format', str(cm.exception))

        with self.assertRaises(ValueError) as cm:
            ss58_decode('MhvaLBvSb5jhjrftHLQPAvJegnpXgyDTE1ZprRNzAcfQSRdbL')

        self.assertEqual('47 is a reserved SS58 format', str(cm.exception))
Ejemplo n.º 3
0
    def test_encode_with_2_byte_prefix(self):
        public_key = ss58_decode('5GoKvZWG5ZPYL1WUovuHW3zJBWBP5eT8CbqjdRY4Q6iMaQua')

        self.assertEqual(
            'yGHU8YKprxHbHdEv7oUK4rzMZXtsdhcXVG2CAMyC9WhzhjH2k',
            ss58_encode(public_key, ss58_format=255)
        )
Ejemplo n.º 4
0
def is_valid_substrate_address(
    chain: SubstrateChain,
    value: str,
) -> bool:
    """Validates a ss58 encoded substrate address for the given chain.

    TODO: this function relies on py-scale-codec `ss58_decode()` for validating
    that a str is a valid substrate address for the given chain. The recent
    changes introduced on the py-scale-codec library have altered the behavior
    of this function by validating positively any str starting with `0x`. An
    issue has been opened regarding this matter (link below). Once py-scale-codec
    implements its own address validation method this function may be no longer
    needed. Issue:
    https://github.com/polkascan/py-scale-codec/issues/27

    Polkascan ss58 utils documentation:
    https://github.com/polkascan/py-substrate-interface/blob/master/substrateinterface/utils/ss58.py  # noqa: E501

    External Address Format (SS58) documentation:
    https://github.com/paritytech/substrate/wiki/External-Address-Format-(SS58)
    """
    if value.startswith('0x'):
        # TODO: temporary patch for py-scale-codec/issue/27
        return False

    if chain == SubstrateChain.KUSAMA:
        valid_ss58_format = 2
    elif chain == SubstrateChain.POLKADOT:
        valid_ss58_format = 0
    else:
        raise AssertionError(f'Unexpected chain: {chain}')

    try:
        ss58_decode(
            address=value,
            valid_ss58_format=valid_ss58_format,
        )
    except ValueError:
        return False

    return True
def get_escrow_address(addresses: list, *, threshold: int = 2):
    _addresses = []
    for addr in addresses:
        _addr = ss58_decode(addr)
        _addr = bytes.fromhex(_addr)
        _addresses.append(_addr)

    _addresses = sorted(_addresses)
    print(_addresses)
    escrow_addr = multisig.multi_account_id(_addresses, threshold)
    escrow_addr = binascii.hexlify(bytearray(escrow_addr)).decode("ascii")
    return ss58_encode(escrow_addr, 2)
    def setUp(self):
        self.buyer_address = ss58_encode(buyer_keypair[0], 2)
        self.seller_address = ss58_encode(seller_keypair[0], 2)
        self.admin_address = ss58_encode(admin_keypair[0], 2)
        self.seller_priv = seller_keypair[1].hex()
        self.seller_pub = ss58_decode(self.seller_address)
        self.admin_priv = admin_keypair[1].hex()
        self.admin_pub = ss58_decode(self.admin_address)

        substrate.init_runtime(block_hash=None)

        # Prepare the inner call as we will reuse it, lets not write code twice
        self.inner_call = ScaleDecoder.get_decoder_class(
            "Call", metadata=substrate.metadata_decoder)

        self.inner_call.encode({
            "call_module": "Balances",
            "call_function": "transfer",
            "call_args": {
                "dest": self.buyer_address,
                "value": settings.trade_value,
            },
        })
Ejemplo n.º 7
0
    def check_transfer_config( config: 'bittensor.Config'):
        if config.subtensor.network == bittensor.defaults.subtensor.network and not config.no_prompt:
            config.subtensor.network = Prompt.ask("Enter subtensor network", choices=bittensor.__networks__, default = bittensor.defaults.subtensor.network)

        if config.wallet.name == bittensor.defaults.wallet.name and not config.no_prompt:
            wallet_name = Prompt.ask("Enter wallet name", default = bittensor.defaults.wallet.name)
            config.wallet.name = str(wallet_name)

        # Get destination.
        if not config.dest:
            dest = Prompt.ask("Enter destination public key: (ss58 or ed2519)")
            if len(dest) == 48:
                try:
                    ss58_decode(dest)
                    config.dest = str(dest)
                except ValueError:
                    console.print(":cross_mark:[red] Invalid public key format[/red] [bold white]{}[/bold white]".format(dest))
                    sys.exit()
            elif len(dest) == 66 or len(dest) == 64:
                try:
                    ss58_encode(dest)
                    config.dest = str(dest)
                except ValueError:
                    console.print(":cross_mark:[red] Invalid ss58 address format[/red] [bold white]{}[/bold white]".format(dest))
                    sys.exit()
            else:
                console.print(":cross_mark:[red] Invalid address format[/red] [bold white]{}[/bold white]".format(dest))
                sys.exit()
                    
        # Get amount.
        if not config.amount:
            amount = Prompt.ask("Enter Tao amount to transfer")
            try:
                config.amount = float(amount)
            except ValueError:
                console.print(":cross_mark:[red] Invalid Tao amount[/red] [bold white]{}[/bold white]".format(amount))
                sys.exit()
Ejemplo n.º 8
0
def test_get_active(setup_chain):
    wallet = generate_wallet()
    subtensor = setup_subtensor(setup_chain)
    metagraph = bittensor.metagraph(subtensor=subtensor)

    subtensor.register(wallet=wallet)
    metagraph.sync()
    result = metagraph.active

    assert isinstance(result, Tensor)
    assert len(result) > 0
    result = metagraph.hotkeys
    elem = result[0]
    elem = "0x" + ss58_decode(elem)
    assert isinstance(elem[0], str)
    assert elem[:2] == "0x"
    assert len(elem[2:]) == 64
    def test_balance_check_rpc_breakdown(self):
        """
        This test breaks down every RPC call that happens to get balance
        It is here only for the purpose of understanding how everything works

        Steps:

        Step 1: Initial preparatory steps
         - Connect to node
         - RPC Call 1: chain_getFinalisedHead
           - Get current finalised block hash

        Step 2: Get MetaData for the current block hash
         - RPC Call 2: state_getMetadata
         - Decode the result using MetadataDecoder and ScaleBytes

        Step 3: Prepare hashed data to make the next RPC call
         - We need three params hashed into one single hash string
           - Storage Module, Storage Function and Payload
         - Each param is encoded and hashed using various hashers
           Hasher for Payload is obtained from the dict at the bottom of the docstring

        Step 4: Get data at the storage hash prepared in Step 3
         - RPC Call 3: state_getStorageAt
         - Decode the data using ScaleDecoder's special class

        This is a key information used to encode/hash/decode in the entire function
        {
            'name': 'Account',
            'modifier': 'Default',
            'type': {
                'MapType': {
                    'hasher': 'Blake2_128Concat',
                    'key': 'AccountId',
                    'value': 'AccountInfo<Index, AccountData>',
                    'isLinked': False
                }
            },
        }
        """
        # Test data
        test_address = "HsgNgA5sgjuKxGUeaZPJE8rRn9RuixjvnPkVLFUYLEpj15G"

        ### STEP 1
        # Connect to the node
        substrate = SubstrateInterface(
            url=settings.NODE_URL,
            address_type=2,
            type_registry_preset="kusama",
        )

        # Get finalised block hash
        block_hash = substrate.rpc_request("chain_getFinalisedHead",
                                           []).get("result")
        if not block_hash:
            raise Exception(
                "ERROR: RPC call for chain_getFinalisedHead failed")

        print("\n\n")
        print("-" * 100)
        print(f"BLOCK HASH: {block_hash}")

        ### STEP 2
        # Get metadata decoder, this is needed later
        metadata_result = substrate.rpc_request("state_getMetadata",
                                                [block_hash]).get("result")
        if not metadata_result:
            raise Exception("ERROR: RPC call for state_getMetadata failed")

        metadata_encoded = MetadataDecoder(ScaleBytes(metadata_result))
        metadata = metadata_encoded.decode()

        ### STEP 3
        # This comes from the metadata dict in the docstring `type` -> `MapType` -> `key`
        map_type_key = "AccountId"
        test_address_modified = "0x{}".format(ss58.ss58_decode(
            test_address, 2))
        print(f"TEST ADDRESS SS58 DECODED: {test_address_modified}")
        scale_decoder = ScaleDecoder.get_decoder_class(map_type_key)
        test_address_encoded = scale_decoder.encode(test_address_modified)
        print(f"TEST ADDRESS ENCODED: {test_address_encoded}")

        # Why blake2_128_concat? Because metadata dict in the docstring `type` -> `MapType` -> `hasher`
        test_address_hash = hasher.blake2_128_concat(test_address_encoded.data)

        # `System` is our module and `Account` if our function for this example
        storage_module = "System"
        storage_function = "Account"
        storage_module_hash = hasher.xxh128(storage_module.encode())
        storage_function_hash = hasher.xxh128(storage_function.encode())

        print(f"STORAGE MODULE: {storage_module}")
        print(f"STORAGE MODULE ENCODED: {storage_module.encode()}")
        print(f"STORAGE MODULE ENCODED HASHED: {storage_module_hash}")

        print(f"STORAGE FUNCTION: {storage_function}")
        print(f"STORAGE FUNCTION ENCODED: {storage_function.encode()}")
        print(f"STORAGE FUNCTION ENCODED HASHED: {storage_function_hash}")

        print(f"TEST ADDRESS: {test_address}")
        print(f"TEST ADDRESS SS58 DECODED: {test_address_modified}")
        print(f"TEST ADDRESS ENCODED: {test_address_encoded}")
        print(f"TEST ADDRESS ENCODED HASHED: {test_address_hash}")

        storage_hash = (f"0x"
                        f"{storage_module_hash}"
                        f"{storage_function_hash}"
                        f"{test_address_hash}")

        print(f"COMBINED HASH: {storage_hash}")

        ### STEP 4
        response = substrate.rpc_request("state_getStorageAt",
                                         [storage_hash, block_hash])
        result = response.get("result")
        if not result:
            raise Exception("ERROR: RPC call for state_getStorageAt failed")

        print(f"RPC RESULT: {result}")
        print("-" * 100)
        print("DECODING ABOVE RESULT ... ...")

        # This is again extracted from the metadata dict in the docstring `type` -> `MapType` -> `value`
        return_type = "AccountInfo<Index, AccountData>"
        result_decoded = ScaleDecoder.get_decoder_class(
            return_type, ScaleBytes(result), metadata=metadata).decode()

        print(f"RESULT DECODED: {result_decoded}")
Ejemplo n.º 10
0
    def test_decode_invalid_checksum(self):
        with self.assertRaises(ValueError) as cm:
            ss58_decode('5GoKvZWG5ZPYL1WUovuHW3zJBWBP5eT8CbqjdRY4Q6iMaQub')

        self.assertEqual('Invalid checksum', str(cm.exception))
Ejemplo n.º 11
0
    def test_decode_empty_string(self):
        with self.assertRaises(ValueError) as cm:
            ss58_decode('')

        self.assertEqual('Empty address provided', str(cm.exception))
Ejemplo n.º 12
0
 def to_multi_address_account_id_filter(info, query, value):
     """ """
     return Transfer.to_multi_address_account_id == ss58_decode(value)
Ejemplo n.º 13
0
def kusama_addr_to_account_id(address):
    decoded_addr = ss58_decode(address)
    decoded_addr_bytes = bytes.fromhex(decoded_addr)
    return decoded_addr_bytes
Ejemplo n.º 14
0
 def multi_address_account_id_filter(info, query, value):
     """ """
     return Extrinsic.multi_address_account_id == ss58_decode(value)
Ejemplo n.º 15
0
 def test_decode_subkey_generated_pairs(self):
     for subkey_pair in self.subkey_pairs:
         self.assertEqual(
             subkey_pair['public_key'],
             '0x' + ss58_decode(address=subkey_pair['address'], valid_ss58_format=subkey_pair['ss58_format'])
         )
Ejemplo n.º 16
0
 def test_decode_public_key(self):
     self.assertEqual(
         '0x03b9dc646dd71118e5f7fda681ad9eca36eb3ee96f344f582fbe7b5bcdebb13077',
         ss58_decode('0x03b9dc646dd71118e5f7fda681ad9eca36eb3ee96f344f582fbe7b5bcdebb13077')
     )
Ejemplo n.º 17
0
 def test_invalid_ss58_format_check(self):
     with self.assertRaises(ValueError):
         ss58_decode('5GoKvZWG5ZPYL1WUovuHW3zJBWBP5eT8CbqjdRY4Q6iMaQua',
                     valid_ss58_format=2)
Ejemplo n.º 18
0
    def test_invalid_ss58_format_check(self):
        with self.assertRaises(ValueError) as cm:
            ss58_decode('5GoKvZWG5ZPYL1WUovuHW3zJBWBP5eT8CbqjdRY4Q6iMaQua', valid_ss58_format=2)

        self.assertEqual('Invalid SS58 format', str(cm.exception))
Ejemplo n.º 19
0
 def test_decode_invalid_checksum(self):
     with self.assertRaises(ValueError):
         ss58_decode('5GoKvZWG5ZPYL1WUovuHW3zJBWBP5eT8CbqjdRY4Q6iMaQub')
Ejemplo n.º 20
0
    def test_decode_invalid_length(self):
        with self.assertRaises(ValueError) as cm:
            ss58_decode('5GoKvZWG5ZPYL1WUovuHW3zJBWBP5eT8CbqjdRY4Q6iMaQubsdhfjksdhfkj')

        self.assertEqual('Invalid address length', str(cm.exception))
Ejemplo n.º 21
0
 def test_decode_invalid_length(self):
     with self.assertRaises(ValueError):
         ss58_decode(
             '5GoKvZWG5ZPYL1WUovuHW3zJBWBP5eT8CbqjdRY4Q6iMaQubsdhfjksdhfkj')