Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Use validators file to stake, unstake, etc #409

Merged
merged 3 commits into from
Feb 8, 2024
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 23 additions & 5 deletions multiversx_sdk_cli/cli_delegation.py
Original file line number Diff line number Diff line change
Expand Up @@ -41,39 +41,44 @@ def setup_parser(args: List[str], subparsers: Any) -> Any:
# remove nodes
sub = cli_shared.add_command_subparser(subparsers, "staking-provider", "remove-nodes",
"Remove nodes must be called by the contract owner")
sub.add_argument("--bls-keys", required=True, help="a list with the bls keys of the nodes")
sub.add_argument("--bls-keys", help="a list with the bls keys of the nodes")
sub.add_argument("--validators-file", help="a JSON file describing the Nodes")
sub.add_argument("--delegation-contract", required=True, help="address of the delegation contract")
_add_common_arguments(args, sub)
sub.set_defaults(func=remove_nodes)

# stake nodes
sub = cli_shared.add_command_subparser(subparsers, "staking-provider", "stake-nodes",
"Stake nodes must be called by the contract owner")
sub.add_argument("--bls-keys", required=True, help="a list with the bls keys of the nodes")
sub.add_argument("--bls-keys", help="a list with the bls keys of the nodes")
sub.add_argument("--validators-file", help="a JSON file describing the Nodes")
sub.add_argument("--delegation-contract", required=True, help="address of the delegation contract")
_add_common_arguments(args, sub)
sub.set_defaults(func=stake_nodes)

# unbond nodes
sub = cli_shared.add_command_subparser(subparsers, "staking-provider", "unbond-nodes",
"Unbond nodes must be called by the contract owner")
sub.add_argument("--bls-keys", required=True, help="a list with the bls keys of the nodes")
sub.add_argument("--bls-keys", help="a list with the bls keys of the nodes")
sub.add_argument("--validators-file", help="a JSON file describing the Nodes")
sub.add_argument("--delegation-contract", required=True, help="address of the delegation contract")
_add_common_arguments(args, sub)
sub.set_defaults(func=unbond_nodes)

# unstake nodes
sub = cli_shared.add_command_subparser(subparsers, "staking-provider", "unstake-nodes",
"Unstake nodes must be called by the contract owner")
sub.add_argument("--bls-keys", required=True, help="a list with the bls keys of the nodes")
sub.add_argument("--bls-keys", help="a list with the bls keys of the nodes")
sub.add_argument("--validators-file", help="a JSON file describing the Nodes")
sub.add_argument("--delegation-contract", required=True, help="address of the delegation contract")
_add_common_arguments(args, sub)
sub.set_defaults(func=unstake_nodes)

# unjail nodes
sub = cli_shared.add_command_subparser(subparsers, "staking-provider", "unjail-nodes",
"Unjail nodes must be called by the contract owner")
sub.add_argument("--bls-keys", required=True, help="a list with the bls keys of the nodes")
sub.add_argument("--bls-keys", help="a list with the bls keys of the nodes")
sub.add_argument("--validators-file", help="a JSON file describing the Nodes")
sub.add_argument("--delegation-contract", required=True, help="address of the delegation contract")
_add_common_arguments(args, sub)
sub.set_defaults(func=unjail_nodes)
Expand Down Expand Up @@ -182,6 +187,7 @@ def add_new_nodes(args: Any):


def remove_nodes(args: Any):
_check_if_either_bls_keys_or_validators_file_are_provided(args)
cli_shared.check_guardian_and_options_args(args)
cli_shared.check_broadcast_args(args)
cli_shared.prepare_chain_id_in_args(args)
Expand All @@ -196,6 +202,7 @@ def remove_nodes(args: Any):


def stake_nodes(args: Any):
_check_if_either_bls_keys_or_validators_file_are_provided(args)
cli_shared.check_guardian_and_options_args(args)
cli_shared.check_broadcast_args(args)
cli_shared.prepare_chain_id_in_args(args)
Expand All @@ -209,7 +216,16 @@ def stake_nodes(args: Any):
cli_shared.send_or_simulate(tx, args)


def _check_if_either_bls_keys_or_validators_file_are_provided(args: Any):
bls_keys = args.bls_keys
validators_file = args.validators_file

if not bls_keys and not validators_file:
raise errors.BadUsage("No bls keys or validators file provided")
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Optionally, can be changed to do this, do that: "Either specify the ..., or the ...".

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Changed



def unbond_nodes(args: Any):
_check_if_either_bls_keys_or_validators_file_are_provided(args)
cli_shared.check_guardian_and_options_args(args)
cli_shared.check_broadcast_args(args)
cli_shared.prepare_chain_id_in_args(args)
Expand All @@ -224,6 +240,7 @@ def unbond_nodes(args: Any):


def unstake_nodes(args: Any):
_check_if_either_bls_keys_or_validators_file_are_provided(args)
cli_shared.check_guardian_and_options_args(args)
cli_shared.check_broadcast_args(args)
cli_shared.prepare_chain_id_in_args(args)
Expand All @@ -238,6 +255,7 @@ def unstake_nodes(args: Any):


def unjail_nodes(args: Any):
_check_if_either_bls_keys_or_validators_file_are_provided(args)
cli_shared.check_guardian_and_options_args(args)
cli_shared.check_broadcast_args(args)
cli_shared.prepare_chain_id_in_args(args)
Expand Down
40 changes: 35 additions & 5 deletions multiversx_sdk_cli/delegation/staking_provider.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
from typing import Any, List, Protocol, Tuple

from multiversx_sdk_core import Address
from multiversx_sdk_core.transaction_factories import \

Check warning on line 5 in multiversx_sdk_cli/delegation/staking_provider.py

View workflow job for this annotation

GitHub Actions / runner / mypy

[mypy] reported by reviewdog 🐶 See https://mypy.readthedocs.io/en/stable/running_mypy.html#missing-imports Raw Output: /home/runner/work/mx-sdk-py-cli/mx-sdk-py-cli/multiversx_sdk_cli/delegation/staking_provider.py:5:1: note: See https://mypy.readthedocs.io/en/stable/running_mypy.html#missing-imports
DelegationTransactionsFactory
from multiversx_sdk_wallet import ValidatorPublicKey

Expand Down Expand Up @@ -82,7 +82,13 @@

def prepare_transaction_for_removing_nodes(self, owner: IAccount, args: Any) -> ITransaction:
delegation_contract = Address.new_from_bech32(args.delegation_contract)
public_keys = self._parse_public_bls_keys(args.bls_keys)

if args.bls_keys:
public_keys = self._parse_public_bls_keys(args.bls_keys)
else:
validators_file_path = Path(args.validators_file).expanduser()
validators_file = ValidatorsFile(validators_file_path)
public_keys = validators_file.load_public_keys()

tx = self._factory.create_transaction_for_removing_nodes(
sender=owner.address,
Expand All @@ -102,7 +108,13 @@

def prepare_transaction_for_staking_nodes(self, owner: IAccount, args: Any) -> ITransaction:
delegation_contract = Address.new_from_bech32(args.delegation_contract)
public_keys = self._parse_public_bls_keys(args.bls_keys)

if args.bls_keys:
public_keys = self._parse_public_bls_keys(args.bls_keys)
else:
validators_file_path = Path(args.validators_file).expanduser()
validators_file = ValidatorsFile(validators_file_path)
public_keys = validators_file.load_public_keys()
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can it be extracted to _load_validator_public_keys(args) (duplicated below)?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Extracted the code in a method


tx = self._factory.create_transaction_for_staking_nodes(
sender=owner.address,
Expand All @@ -122,7 +134,13 @@

def prepare_transaction_for_unbonding_nodes(self, owner: IAccount, args: Any) -> ITransaction:
delegation_contract = Address.new_from_bech32(args.delegation_contract)
public_keys = self._parse_public_bls_keys(args.bls_keys)

if args.bls_keys:
public_keys = self._parse_public_bls_keys(args.bls_keys)
else:
validators_file_path = Path(args.validators_file).expanduser()
validators_file = ValidatorsFile(validators_file_path)
public_keys = validators_file.load_public_keys()

tx = self._factory.create_transaction_for_unbonding_nodes(
sender=owner.address,
Expand All @@ -142,7 +160,13 @@

def prepare_transaction_for_unstaking_nodes(self, owner: IAccount, args: Any) -> ITransaction:
delegation_contract = Address.new_from_bech32(args.delegation_contract)
public_keys = self._parse_public_bls_keys(args.bls_keys)

if args.bls_keys:
public_keys = self._parse_public_bls_keys(args.bls_keys)
else:
validators_file_path = Path(args.validators_file).expanduser()
validators_file = ValidatorsFile(validators_file_path)
public_keys = validators_file.load_public_keys()

tx = self._factory.create_transaction_for_unstaking_nodes(
sender=owner.address,
Expand All @@ -162,7 +186,13 @@

def prepare_transaction_for_unjailing_nodes(self, owner: IAccount, args: Any) -> ITransaction:
delegation_contract = Address.new_from_bech32(args.delegation_contract)
public_keys = self._parse_public_bls_keys(args.bls_keys)

if args.bls_keys:
public_keys = self._parse_public_bls_keys(args.bls_keys)
else:
validators_file_path = Path(args.validators_file).expanduser()
validators_file = ValidatorsFile(validators_file_path)
public_keys = validators_file.load_public_keys()

tx = self._factory.create_transaction_for_unjailing_nodes(
sender=owner.address,
Expand Down
43 changes: 41 additions & 2 deletions multiversx_sdk_cli/tests/test_cli_staking_provider.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@

first_bls_key = "f8910e47cf9464777c912e6390758bb39715fffcb861b184017920e4a807b42553f2f21e7f3914b81bcf58b66a72ab16d97013ae1cff807cefc977ef8cbf116258534b9e46d19528042d16ef8374404a89b184e0a4ee18c77c49e454d04eae8d"
second_bls_key = "1b4e60e6d100cdf234d3427494dac55fbac49856cadc86bcb13a01b9bb05a0d9143e86c186c948e7ae9e52427c9523102efe9019a2a9c06db02993f2e3e6756576ae5a3ec7c235d548bc79de1a6990e1120ae435cb48f7fc436c9f9098b92a0d"
validators_file = parent / "testdata" / "validators_file.json"


def test_create_new_delegation_contract(capsys: Any):
Expand Down Expand Up @@ -53,7 +54,7 @@ def test_add_nodes(capsys: Any):
assert transaction["receiver"] == "erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqthllllsy5r6rh"


def test_remove_nodes(capsys: Any):
def test_remove_nodes_with_bls_keys(capsys: Any):
main([
"staking-provider", "remove-nodes",
"--bls-keys", f"{first_bls_key},{second_bls_key}",
Expand All @@ -72,7 +73,45 @@ def test_remove_nodes(capsys: Any):
assert transaction["gasLimit"] == 13645500


def test_stake_nodes(capsys: Any):
def test_remove_nodes_with_validators_file(capsys: Any):
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🚀

main([
"staking-provider", "remove-nodes",
"--validators-file", str(validators_file),
"--delegation-contract", "erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqthllllsy5r6rh",
"--pem", str(alice),
"--chain", "T",
"--nonce", "7", "--estimate-gas"
])
tx = get_transaction(capsys)
data = tx["emittedTransactionData"]
transaction = tx["emittedTransaction"]

assert data == "removeNodes@f8910e47cf9464777c912e6390758bb39715fffcb861b184017920e4a807b42553f2f21e7f3914b81bcf58b66a72ab16d97013ae1cff807cefc977ef8cbf116258534b9e46d19528042d16ef8374404a89b184e0a4ee18c77c49e454d04eae8d@1b4e60e6d100cdf234d3427494dac55fbac49856cadc86bcb13a01b9bb05a0d9143e86c186c948e7ae9e52427c9523102efe9019a2a9c06db02993f2e3e6756576ae5a3ec7c235d548bc79de1a6990e1120ae435cb48f7fc436c9f9098b92a0d"
assert transaction["sender"] == "erd1qyu5wthldzr8wx5c9ucg8kjagg0jfs53s8nr3zpz3hypefsdd8ssycr6th"
assert transaction["receiver"] == "erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqthllllsy5r6rh"
assert transaction["gasLimit"] == 13645500


def test_stake_nodes_with_bls_keys(capsys: Any):
main([
"staking-provider", "stake-nodes",
"--validators-file", str(validators_file),
"--delegation-contract", "erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqthllllsy5r6rh",
"--pem", str(alice),
"--chain", "T",
"--nonce", "7", "--estimate-gas"
])
tx = get_transaction(capsys)
data = tx["emittedTransactionData"]
transaction = tx["emittedTransaction"]

assert data == "stakeNodes@f8910e47cf9464777c912e6390758bb39715fffcb861b184017920e4a807b42553f2f21e7f3914b81bcf58b66a72ab16d97013ae1cff807cefc977ef8cbf116258534b9e46d19528042d16ef8374404a89b184e0a4ee18c77c49e454d04eae8d@1b4e60e6d100cdf234d3427494dac55fbac49856cadc86bcb13a01b9bb05a0d9143e86c186c948e7ae9e52427c9523102efe9019a2a9c06db02993f2e3e6756576ae5a3ec7c235d548bc79de1a6990e1120ae435cb48f7fc436c9f9098b92a0d"
assert transaction["sender"] == "erd1qyu5wthldzr8wx5c9ucg8kjagg0jfs53s8nr3zpz3hypefsdd8ssycr6th"
assert transaction["receiver"] == "erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqthllllsy5r6rh"
assert transaction["gasLimit"] == 18644000


def test_stake_nodes_with_validators_file(capsys: Any):
main([
"staking-provider", "stake-nodes",
"--bls-keys", f"{first_bls_key},{second_bls_key}",
Expand Down
4 changes: 4 additions & 0 deletions multiversx_sdk_cli/tests/testdata/validator_01.pem
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
-----BEGIN PRIVATE KEY for f8910e47cf9464777c912e6390758bb39715fffcb861b184017920e4a807b42553f2f21e7f3914b81bcf58b66a72ab16d97013ae1cff807cefc977ef8cbf116258534b9e46d19528042d16ef8374404a89b184e0a4ee18c77c49e454d04eae8d-----
N2MxOWJmM2EwYzU3Y2RkMWZiMDhlNDYwN2NlYmFhMzY0N2Q2YjkyNjFiNDY5M2Y2
MWU5NmU1NGIyMThkNDQyYQ==
-----END PRIVATE KEY for f8910e47cf9464777c912e6390758bb39715fffcb861b184017920e4a807b42553f2f21e7f3914b81bcf58b66a72ab16d97013ae1cff807cefc977ef8cbf116258534b9e46d19528042d16ef8374404a89b184e0a4ee18c77c49e454d04eae8d-----
4 changes: 4 additions & 0 deletions multiversx_sdk_cli/tests/testdata/validator_02.pem
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
-----BEGIN PRIVATE KEY for 1b4e60e6d100cdf234d3427494dac55fbac49856cadc86bcb13a01b9bb05a0d9143e86c186c948e7ae9e52427c9523102efe9019a2a9c06db02993f2e3e6756576ae5a3ec7c235d548bc79de1a6990e1120ae435cb48f7fc436c9f9098b92a0d-----
MzAzNGIxZDU4NjI4YTg0Mjk4NGRhMGM3MGRhMGI1YTI1MWViYjJhZWJmNTFhZmM1
YjU4NmUyODM5YjVlNTI2Mw==
-----END PRIVATE KEY for 1b4e60e6d100cdf234d3427494dac55fbac49856cadc86bcb13a01b9bb05a0d9143e86c186c948e7ae9e52427c9523102efe9019a2a9c06db02993f2e3e6756576ae5a3ec7c235d548bc79de1a6990e1120ae435cb48f7fc436c9f9098b92a0d-----
10 changes: 10 additions & 0 deletions multiversx_sdk_cli/tests/testdata/validators_file.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
{
"validators": [
{
"pemFile": "validator_01.pem"
},
{
"pemFile": "validator_02.pem"
}
]
}
14 changes: 14 additions & 0 deletions multiversx_sdk_cli/validators/validators_file.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
from typing import List

from multiversx_sdk_wallet import ValidatorSigner
from multiversx_sdk_wallet.validator_keys import ValidatorPublicKey
from multiversx_sdk_wallet.validator_pem import ValidatorPEM

from multiversx_sdk_cli import guards
Expand Down Expand Up @@ -34,6 +35,19 @@ def load_signers(self) -> List[ValidatorSigner]:

return signers

def load_public_keys(self) -> List[ValidatorPublicKey]:
public_keys: List[ValidatorPublicKey] = []

for validator in self.get_validators_list():
# Get path of "pemFile", make it absolute
validator_pem = Path(validator.get("pemFile")).expanduser()
ssd04 marked this conversation as resolved.
Show resolved Hide resolved
validator_pem = validator_pem if validator_pem.is_absolute() else self.validators_file_path.parent / validator_pem

pem_file = ValidatorPEM.from_file(validator_pem)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These 3 lines can also be extracted to a separate function e.g. load_validator_pem(path): ValidatorPEM / optional (code exists above, as well).

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

extracted in a method

public_keys.append(pem_file.secret_key.generate_public_key())

return public_keys

def _read_json_file_validators(self):
val_file = self.validators_file_path.expanduser()
guards.is_file(val_file)
Expand Down
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ build-backend = "hatchling.build"

[project]
name = "multiversx-sdk-cli"
version = "9.4.1"
version = "9.5.0"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍

authors = [
{ name="MultiversX" },
]
Expand Down
Loading