Skip to content

Commit

Permalink
Get information about public key by public key address (#17)
Browse files Browse the repository at this point in the history
  • Loading branch information
anastasiia-bilova authored May 2, 2019
1 parent bc3ba52 commit 079d447
Show file tree
Hide file tree
Showing 12 changed files with 426 additions and 16 deletions.
31 changes: 30 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -195,14 +195,43 @@ $ remme public-key get-list \
--node-url=node-genesis-testnet.remme.io
{
"result": {
"public_key_addresses": [
"addresses": [
"a23be10b3aad1b4a98f338c71d6dcdb2aa2f296c7e31fb400615e335dc10dd1d4f62bf",
"a23be14b362514d624c1985277005327f6fc40413fb090eee6fccb673a32c9809060ff"
]
}
}
```

Get information about public key by its address — ``remme public-key get-info``:

| Arguments | Type | Required | Description |
| :-------: | :----: | :------: | ---------------------------------------------------------- |
| address | String | Yes | Public key address to get information about public key by. |
| node-url | String | No | Node URL to apply a command to. |

```bash
$ remme public-key get-info \
--address=a23be17addad8eeb5177a395ea47eb54b4a646f8c570f4a2ecc0b1d2f6241c6845181b \
--node-url=node-genesis-testnet.remme.io
{
"result": {
"information": {
"address": "a23be10d215132aee9377cfe26b6d301d32da070a799c227fb4701103e5626d48cd6ba",
"entity_hash": "1edd6d5b1c722a83e03b17180b888d89ec4c079a0044f074b7c8bb2720cad8ba4e97a80c7edbd24c1824f5312dfd8a0877453394a63410b52c1f16e1d60ef754",
"entity_hash_signature": "1322ca51fb6d33e44d2b6c028eb668b5712a5277bbdea089112203e8e950d1c7d02d446291865a2f5fca4c6767fb84583e53205df850f1fc05ea6f22c736635f425b0159881f7f998da52378bf08353d87d2a2c226a7ababea9a245e69be06d54c573a42c3be907ca49589a67b5e9cc4d8ed12cea8546b2df531fd9620f4dc71869d8fa0bfcbef239d9a6e2e3bf12bcac4fd562b22ff408d7b077b75d8e59af0348264a7c9e7e61b4c5f844636a0fbbcfae61955efdf10323a992ea2a1734eb0ee7952519b00e696a02e7460771b0e0887e011b709e88abfda896b68150c08dcf6b4bf7c70f996f6031c13311056ab935ce1fdf63d3f19b5a3ca6ae604c4f12b",
"is_revoked": false,
"is_valid": true,
"owner_public_key": "03738df3f4ac3621ba8e89413d3ff4ad036c3a0a4dbb164b695885aab6aab614ad",
"public_key": "30820122300d06092a864886f70d01010105000382010f003082010a02820101008b29cc5ec32dab21b48b63faf2fd00f88879b9d4286c3cde6218d19263ea8226fce499039968c5f9736149e298bbc56680b516f2d83507d88fb95771445ca3c59bcdbb31bb5993a4e5dfcd2c4bc86328ec76e95e2f4582f9cac8223a2f16a2b14c4358b6fb105e37baf9daa9bd5b708ab204d8015a1ce782e28024eae1801151616c90a3b1aa1916d5b8dd021b3aa4cec77450660841f8619a7234c6199d01ccd43b1d6ff7fa5f50bf80bc06b682b126bdca0753a6830b7a95afca79442ec64fd09ddcc34627dcbdad0c5e66317db98d0e1c24c3f992b83f4b0f97e2b0300a2cb51e33eccf060f26b4e19a88f15216f8c17be5f5e023a1f260f7c93a2a4523ed0203010001",
"type": "rsa",
"valid_from": 1556118334,
"valid_to": 1587222334
}
}
}
```

## Development

<h3 id="development-requirements">Requirements</h4>
Expand Down
5 changes: 3 additions & 2 deletions cli/constants.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,16 +3,17 @@
"""
ADDRESS_REGEXP = r'^[0-9a-f]{70}$'
BATCH_ID_REGEXP = r'^[0-9a-f]{128}$'
PUBLIC_KEY_REGEXP = r'^[0-9a-f]{66}$'
PRIVATE_KEY_REGEXP = r'^[a-f0-9]{64}$'
PUBLIC_KEY_REGEXP = r'^[0-9a-f]{66}$'
PUBLIC_KEY_ADDRESS_REGEXP = r'^[0-9a-f]{70}$'
HEADER_SIGNATURE_REGEXP = r'^[0-9a-f]{128}$'
DOMAIN_NAME_REGEXP = r'(?:[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?\.)+[a-z0-9][a-z0-9-]{0,61}[a-z0-9]'

PASSED_EXIT_FROM_COMMAND_CODE = 0
FAILED_EXIT_FROM_COMMAND_CODE = -1
INCORRECT_ENTERED_COMMAND_CODE = 2

NODE_URL_ARGUMENT_HELP_MESSAGE = 'Apply the command to the specified node by its URL.'
NODE_URL_ARGUMENT_HELP_MESSAGE = 'Node URL to apply a command to.'

CLI_CONFIG_FILE_NAME = 'remme-core-cli'

Expand Down
21 changes: 21 additions & 0 deletions cli/generic/forms/fields.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
ADDRESS_REGEXP,
DOMAIN_NAME_REGEXP,
PRIVATE_KEY_REGEXP,
PUBLIC_KEY_ADDRESS_REGEXP,
)


Expand Down Expand Up @@ -81,3 +82,23 @@ def _deserialize(self, value, attr, data, **kwargs):
raise ValidationError(f'The following private key `{private_key}` is invalid.')

return value


class PublicKeyAddressField(fields.Field):
"""
Implements validation of the public key address.
References:
- https://marshmallow.readthedocs.io/en/3.0/custom_fields.html
"""

def _deserialize(self, value, attr, data, **kwargs):
"""
Validate data (public key address) that was passed to field.
"""
public_key_address = value

if re.match(pattern=PUBLIC_KEY_ADDRESS_REGEXP, string=public_key_address) is None:
raise ValidationError(f'The following public key address `{public_key_address}` is invalid.')

return value
48 changes: 43 additions & 5 deletions cli/public_key/cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,14 @@
FAILED_EXIT_FROM_COMMAND_CODE,
NODE_URL_ARGUMENT_HELP_MESSAGE,
)
from cli.public_key.forms import GetPublicKeysForm
from cli.public_key.help import ADDRESS_ARGUMENT_HELP_MESSAGE
from cli.public_key.forms import (
GetPublicKeyInformationForm,
GetPublicKeysForm,
)
from cli.public_key.help import (
ACCOUNT_ADDRESS_ARGUMENT_HELP_MESSAGE,
PUBLIC_KEY_ADDRESS_ARGUMENT_HELP_MESSAGE,
)
from cli.public_key.service import PublicKey
from cli.utils import (
default_node_url,
Expand All @@ -28,7 +34,39 @@ def public_key_commands():
pass


@click.option('--address', type=str, required=True, help=ADDRESS_ARGUMENT_HELP_MESSAGE)
@click.option('--address', type=str, required=True, help=PUBLIC_KEY_ADDRESS_ARGUMENT_HELP_MESSAGE)
@click.option('--node-url', type=str, required=False, help=NODE_URL_ARGUMENT_HELP_MESSAGE, default=default_node_url())
@public_key_commands.command('get-info')
def get_public_key_info(address, node_url):
"""
Get information about public key by its address.
"""
arguments, errors = GetPublicKeyInformationForm().load({
'address': address,
'node_url': node_url,
})

if errors:
print_errors(errors)
sys.exit(FAILED_EXIT_FROM_COMMAND_CODE)

public_key_address = arguments.get('address')
node_url = arguments.get('node_url')

remme = Remme(network_config={
'node_address': str(node_url) + ':8080',
})

result, errors = PublicKey(service=remme).get(address=public_key_address)

if errors is not None:
print_errors(errors=errors)
sys.exit(FAILED_EXIT_FROM_COMMAND_CODE)

print_result(result=result)


@click.option('--address', type=str, required=True, help=ACCOUNT_ADDRESS_ARGUMENT_HELP_MESSAGE)
@click.option('--node-url', type=str, required=False, help=NODE_URL_ARGUMENT_HELP_MESSAGE, default=default_node_url())
@public_key_commands.command('get-list')
def get_public_keys(address, node_url):
Expand All @@ -44,14 +82,14 @@ def get_public_keys(address, node_url):
print_errors(errors)
sys.exit(FAILED_EXIT_FROM_COMMAND_CODE)

address = arguments.get('address')
account_address = arguments.get('address')
node_url = arguments.get('node_url')

remme = Remme(network_config={
'node_address': str(node_url) + ':8080',
})

result, errors = PublicKey(service=remme).get_list(address=address)
result, errors = PublicKey(service=remme).get_list(address=account_address)

if errors is not None:
print_errors(errors=errors)
Expand Down
10 changes: 10 additions & 0 deletions cli/public_key/forms.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,19 @@
from cli.generic.forms.fields import (
AccountAddressField,
NodeURLField,
PublicKeyAddressField,
)


class GetPublicKeyInformationForm(Schema):
"""
Get information about public key of the public key information form.
"""

address = PublicKeyAddressField(required=True)
node_url = NodeURLField(allow_none=True, required=False)


class GetPublicKeysForm(Schema):
"""
Get a list of the addresses of the public keys form.
Expand Down
3 changes: 2 additions & 1 deletion cli/public_key/help.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
"""
Provide help messages for command line interface's public key commands.
"""
ADDRESS_ARGUMENT_HELP_MESSAGE = 'Account address to get a list of the addresses of the public keys by.'
ACCOUNT_ADDRESS_ARGUMENT_HELP_MESSAGE = 'Account address to get a list of the addresses of the public keys by.'
PUBLIC_KEY_ADDRESS_ARGUMENT_HELP_MESSAGE = 'Public key address to get information about public key by.'
6 changes: 6 additions & 0 deletions cli/public_key/interfaces.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,12 @@ class PublicKeyInterface:
Implements public key interface.
"""

def get(self, address):
"""
Get information about public key by its address.
"""
pass

def get_list(self, address):
"""
Get a list of the addresses of the public keys by account address.
Expand Down
22 changes: 21 additions & 1 deletion cli/public_key/service.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
import asyncio

from accessify import implements
from aiohttp_json_rpc import RpcGenericServerDefinedError

from cli.public_key.interfaces import PublicKeyInterface

Expand All @@ -25,6 +26,25 @@ def __init__(self, service):
"""
self.service = service

def get(self, address):
"""
Get information about public key by its address.
"""
try:
public_key_info = loop.run_until_complete(
self.service.public_key_storage.get_info(public_key_address=address),
)

except RpcGenericServerDefinedError as error:
return None, str(error.message)

except Exception as error:
return None, str(error)

return {
'information': public_key_info.data,
}, None

def get_list(self, address):
"""
Get a list of the addresses of the public keys by account address.
Expand All @@ -38,5 +58,5 @@ def get_list(self, address):
return None, str(error)

return {
'public_key_addresses': public_key_addresses,
'addresses': public_key_addresses,
}, None
2 changes: 1 addition & 1 deletion setup.cfg
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ combine_as_imports=True
max-line-length=120
ignore=D200, D413, D107, D100
per-file-ignores=
*/__init__.py: D104, F401, D100
*/__init__.py: D104, F401, D100,
*/test_*: D205

[coverage:run]
Expand Down
45 changes: 45 additions & 0 deletions tests/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,43 @@ def batch_id(self):
'08f5308af03fd4aa18ff1d868f043b12dd7b0a792e141f000a2505acd4b7a956'


class PublicKeyInformation:
"""
Impose public key information data transfer object.
"""

@property
def data(self):
"""
Get public key information.
"""
return {
'address': 'a23be1ae97d605bcbe61c312d9a443c010dbe7e6a0761e24b10d5368829ab0a7d36acc',
'entity_hash': '13517cee1694346b584c08f5d84cc584b407043ef6a682942b1e18f0466cf1e2'
'dede1756499ac8a2ee495cba258c609ea6147b4daa15225ba60ec5ffca419bd6',
'entity_hash_signature': '6e081607aac18e63a44265e0054fb3e60d3791ac2292925c56d54df216396a3af42e96557a0da09b'
'236cdb5970ca5272473dcc9d71f16978e09a26bfb5e96562d8002473cfdf29b4c04dcc97cd4fa9d7'
'68ea13bd04b7479fe2f5965cfb0f944848511c9f597eacd4a23a1fd66aabfa95f45130fae1ae2507'
'e8ed8d8ee308c77a042c86bbc476e2d3ed46c4b3c2a86c87470bb94c6e266cfd44bc513d04e5523c'
'7faf08887df4e37f2e31bda1bf403cb7bb3145602cd56dea7965e6e417d86620704a68013e95bbda'
'6a81e3dfb86aa489fa060e78bf9edfc4329ffc1f8484ecc610fccb5302499e1f18d0e2584db9c23c'
'db4b0485ccda7cab17896b8fec28c851',
'is_revoked': False,
'is_valid': True,
'owner_public_key': '03738df3f4ac3621ba8e89413d3ff4ad036c3a0a4dbb164b695885aab6aab614ad',
'public_key': '30820122300d06092a864886f70d01010105000382010f003082010a028201010098ed61c659566b05d4017a0b5'
'9b7ce15f6be8432a470713cf3f0ac40b9ded6b65c227704c9bbde4f41a81a380c1ebadb771d1295418805eb16d5'
'14c0eb8a8747d08bb1cb5269d5ecb1152d64a8d8bb14836589f6babce22c2deac7dc6b80fcf285c74b67c5ccaf7'
'464df47d10dccecf02d8c4ed9924a8f4ee0df8661d9378fdb0a42355eda8128e88f7871ac5ea7c2605afa1b2b40'
'0e1a13b9f9fcf037aa7defcfe2abdcc4b9635d8601d1755660c0838fb2e10c35a88e7b9c1fc89db58cb6fa701a8'
'a80f3dbbf587c1af43e7029e4bc79a26012cb9534d66a818c68acb9707a1a1a7c02b781df4928540053693696fb'
'058d1935fed35cf307c362e7f601710b0203010001',
'type': 'rsa',
'valid_from': 1554753277,
'valid_to': 1585857277,
}


class NodeConfigurations:
"""
Impose node configurations data transfer object.
Expand All @@ -137,6 +174,14 @@ def sent_transaction():
return SentTransaction()


@pytest.fixture()
def public_key_info():
"""
Get public key information fixture.
"""
return PublicKeyInformation()


@pytest.fixture()
def node_configurations():
"""
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,10 @@
from click.testing import CliRunner

from cli.constants import (
ADDRESS_REGEXP,
FAILED_EXIT_FROM_COMMAND_CODE,
NODE_IP_ADDRESS_FOR_TESTING,
PASSED_EXIT_FROM_COMMAND_CODE,
PUBLIC_KEY_ADDRESS_REGEXP,
)
from cli.entrypoint import cli
from cli.utils import dict_to_pretty_json
Expand All @@ -33,12 +33,12 @@ def test_get_public_keys():
NODE_IP_ADDRESS_FOR_TESTING,
])

public_key_addresses = json.loads(result.output).get('result').get('public_key_addresses')
public_key_addresses = json.loads(result.output).get('result').get('addresses')

assert PASSED_EXIT_FROM_COMMAND_CODE == result.exit_code

for public_key in public_key_addresses:
assert re.match(pattern=ADDRESS_REGEXP, string=public_key) is not None
assert re.match(pattern=PUBLIC_KEY_ADDRESS_REGEXP, string=public_key) is not None


def test_get_public_keys_invalid_address():
Expand Down Expand Up @@ -83,7 +83,7 @@ def test_get_public_keys_without_node_url(mocker):

expected_result = {
'result': {
'public_key_addresses': public_key_addresses,
'addresses': public_key_addresses,
},
}

Expand Down Expand Up @@ -195,7 +195,7 @@ def test_get_public_keys_non_existing_address():
NODE_IP_ADDRESS_FOR_TESTING,
])

public_key_addresses = json.loads(result.output).get('result').get('public_key_addresses')
public_key_addresses = json.loads(result.output).get('result').get('addresses')

assert PASSED_EXIT_FROM_COMMAND_CODE == result.exit_code
assert isinstance(public_key_addresses, list)
Expand Down
Loading

0 comments on commit 079d447

Please sign in to comment.