Skip to content
This repository has been archived by the owner on Dec 15, 2021. It is now read-only.

IS-1215: Add debug_get_account api #511

Merged
merged 4 commits into from
Sep 2, 2020
Merged
Show file tree
Hide file tree
Changes from all 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
10 changes: 9 additions & 1 deletion iconservice/base/type_converter_templates.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ class ParamType(IntEnum):
ICX_GET_TOTAL_SUPPLY = 303
ICX_GET_SCORE_API = 304
ISE_GET_STATUS = 305
DEBUG_GET_ACCOUNT = 306

WRITE_PRECOMMIT = 400
# REMOVE_PRECOMMIT = 500
Expand Down Expand Up @@ -161,6 +162,7 @@ class ConstantKeys:
ICX_GET_TOTAL_SUPPLY = "icx_getTotalSupply"
ICX_GET_SCORE_API = "icx_getScoreApi"
ISE_GET_STATUS = "ise_getStatus"
DEBUG_GET_ACCOUNT = "debug_getAccount"

DEPOSIT_TERM = "term"
DEPOSIT_ID = "id"
Expand Down Expand Up @@ -304,6 +306,11 @@ class ConstantKeys:
ConstantKeys.FILTER: [ValueType.STRING]
}

type_convert_templates[ParamType.DEBUG_GET_ACCOUNT] = {
ConstantKeys.ADDRESS: ValueType.ADDRESS,
ConstantKeys.FILTER: ValueType.INT
}

type_convert_templates[ParamType.QUERY] = {
ConstantKeys.METHOD: ValueType.STRING,
ConstantKeys.PARAMS: {
Expand All @@ -313,7 +320,8 @@ class ConstantKeys:
ConstantKeys.ICX_GET_BALANCE: type_convert_templates[ParamType.ICX_GET_BALANCE],
ConstantKeys.ICX_GET_TOTAL_SUPPLY: type_convert_templates[ParamType.ICX_GET_TOTAL_SUPPLY],
ConstantKeys.ICX_GET_SCORE_API: type_convert_templates[ParamType.ICX_GET_SCORE_API],
ConstantKeys.ISE_GET_STATUS: type_convert_templates[ParamType.ISE_GET_STATUS]
ConstantKeys.ISE_GET_STATUS: type_convert_templates[ParamType.ISE_GET_STATUS],
ConstantKeys.DEBUG_GET_ACCOUNT: type_convert_templates[ParamType.DEBUG_GET_ACCOUNT],
}
}
}
Expand Down
1 change: 1 addition & 0 deletions iconservice/icon_constant.py
Original file line number Diff line number Diff line change
Expand Up @@ -472,3 +472,4 @@ class RPCMethod:
ICX_CALL = 'icx_call'
ICX_SEND_TRANSACTION = 'icx_sendTransaction'
DEBUG_ESTIMATE_STEP = "debug_estimateStep"
DEBUG_GET_ACCOUNT = "debug_getAccount"
3 changes: 2 additions & 1 deletion iconservice/icon_inner_service.py
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,8 @@
RPCMethod.ICX_GET_SCORE_API: THREAD_STATUS,
RPCMethod.ISE_GET_STATUS: THREAD_STATUS,
RPCMethod.ICX_CALL: THREAD_QUERY,
RPCMethod.DEBUG_ESTIMATE_STEP: THREAD_ESTIMATE
RPCMethod.DEBUG_ESTIMATE_STEP: THREAD_ESTIMATE,
RPCMethod.DEBUG_GET_ACCOUNT: THREAD_QUERY,
}

_TAG = "MQ"
Expand Down
31 changes: 28 additions & 3 deletions iconservice/icon_service_engine.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@
from typing import TYPE_CHECKING, List, Optional, Tuple, Dict, Union, Any

from iconcommons.logger import Logger

from iconservice.rollback import check_backup_exists
from iconservice.rollback.backup_cleaner import BackupCleaner
from iconservice.rollback.backup_manager import BackupManager
Expand Down Expand Up @@ -64,7 +63,9 @@
from .icx import IcxEngine, IcxStorage
from .icx.issue import IssueEngine, IssueStorage
from .icx.issue.base_transaction_creator import BaseTransactionCreator
from .icx.unstake_patcher import UnstakePatcher, INVALID_EXPIRED_UNSTAKES_FILENAME
from .icx.storage import AccountPartFlag
from .icx.unstake_patcher import INVALID_EXPIRED_UNSTAKES_FILENAME
from .icx.unstake_patcher import UnstakePatcher
from .iiss import check_decentralization_condition
from .iiss.engine import Engine as IISSEngine
from .iiss.reward_calc import RewardCalcStorage
Expand Down Expand Up @@ -126,7 +127,8 @@ def __init__(self):
RPCMethod.ISE_GET_STATUS: self._handle_ise_get_status,
RPCMethod.ICX_CALL: self._handle_icx_call,
RPCMethod.DEBUG_ESTIMATE_STEP: self._handle_estimate_step,
RPCMethod.ICX_SEND_TRANSACTION: self._handle_icx_send_transaction
RPCMethod.ICX_SEND_TRANSACTION: self._handle_icx_send_transaction,
RPCMethod.DEBUG_GET_ACCOUNT: self._handle_debug_get_account
}

self._precommit_data_manager = PrecommitDataManager()
Expand Down Expand Up @@ -2127,3 +2129,26 @@ def _run_unstake_patcher(self, context: 'IconScoreContext'):
)

Logger.info(tag=_TAG, msg="_run_unstake_patcher() end")

@classmethod
def _handle_debug_get_account(
cls,
context: 'IconScoreContext',
params: dict
) -> dict:
"""
Handles get raw data of account in StateDB

:param context: context
:param params: parameters of account address and filter
:return: account raw data of stateDB
"""

address: 'Address' = params["address"]
account_filter: 'AccountPartFlag' = AccountPartFlag(params["filter"])
raw_data: dict = context.engine.icx.get_account_raw_data(
context=context,
address=address,
account_filter=account_filter
)
return raw_data
60 changes: 60 additions & 0 deletions iconservice/icx/engine.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,12 +17,16 @@
from typing import TYPE_CHECKING

from .icx_account import Account
from .storage import AccountPartFlag
from ..base.ComponentBase import EngineBase
from ..base.address import Address
from ..base.exception import InvalidParamsException

if TYPE_CHECKING:
from ..iconscore.icon_score_context import IconScoreContext
from .coin_part import CoinPart
from .stake_part import StakePart
from .delegation_part import DelegationPart


class Engine(EngineBase):
Expand Down Expand Up @@ -97,3 +101,59 @@ def _transfer(self,
context.storage.icx.put_account(context, to_account)

return True

@classmethod
def get_account_raw_data(
cls,
context: 'IconScoreContext',
address: 'Address',
account_filter: 'AccountPartFlag'
) -> dict:
"""Get the balance of address

:param context:
:param address: account address
:param account_filter:
:return: raw data of account in stateDB
"""

ret = {}
if AccountPartFlag.COIN in account_filter:
part: 'CoinPart' = context.storage.icx.get_part(
context=context,
flag=AccountPartFlag.COIN,
address=address
)
ret["coin"] = {
"type": part.type.value,
"typeStr": str(part.type),
"flag": part.flags.value,
"flagStr": str(part.flags),
"balance": part.balance
}
if AccountPartFlag.STAKE in account_filter:
part: 'StakePart' = context.storage.icx.get_part(
context=context,
flag=AccountPartFlag.STAKE,
address=address
)
ret["stake"] = {
"stake": part.stake,
"unstake": part.unstake,
"unstakeBlockHeight": part.unstake_block_height,
"unstakesInfo": part.unstakes_info,
}
if AccountPartFlag.DELEGATION in account_filter:
part: 'DelegationPart' = context.storage.icx.get_part(
context=context,
flag=AccountPartFlag.DELEGATION,
address=address
)
ret["delegation"] = {
"totalDelegated": part.delegated_amount,
"delegations": [
{"address": delegation[0], "value": delegation[1]}
for delegation in part.delegations
],
}
return ret
28 changes: 19 additions & 9 deletions iconservice/icx/storage.py
Original file line number Diff line number Diff line change
Expand Up @@ -310,9 +310,11 @@ def get_treasury_account(self, context: 'IconScoreContext') -> 'Account':
"""
return context.storage.icx.get_account(context, context.storage.icx.fee_treasury)

def _get_part(self, context: 'IconScoreContext',
part_class: Union[type(CoinPart), type(StakePart), type(DelegationPart)],
address: 'Address') -> Union['CoinPart', 'StakePart', 'DelegationPart']:
def _get_part(
self,
context: 'IconScoreContext',
part_class: Union[type(CoinPart), type(StakePart), type(DelegationPart)],
address: 'Address') -> Union['CoinPart', 'StakePart', 'DelegationPart']:
key: bytes = part_class.make_key(address)
value: bytes = self._db.get(context, key)

Expand Down Expand Up @@ -391,13 +393,21 @@ def put_total_supply(self,
value = value.to_bytes(DEFAULT_BYTE_SIZE, DATA_BYTE_ORDER)
self._db.put(context, self._TOTAL_SUPPLY_KEY, value)

def get_coin_part(self, context: 'IconScoreContext', address: 'Address') -> 'CoinPart':
part: 'CoinPart' = self._get_part(context, CoinPart, address)
part.set_complete(True)
return part
def get_part(
self,
context: 'IconScoreContext',
flag: 'AccountPartFlag',
address: 'Address'
) -> Union['CoinPart', 'StakePart', 'DelegationPart']:

if AccountPartFlag.COIN == flag:
part_class = CoinPart
elif AccountPartFlag.STAKE == flag:
part_class = StakePart
else:
part_class = DelegationPart

def get_stake_part(self, context: 'IconScoreContext', address: 'Address') -> 'StakePart':
part: 'StakePart' = self._get_part(context, StakePart, address)
part: Union['CoinPart', 'StakePart', 'DelegationPart'] = self._get_part(context, part_class, address)
part.set_complete(True)
return part

Expand Down
6 changes: 3 additions & 3 deletions iconservice/icx/unstake_patcher.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
from typing import TYPE_CHECKING, List, Dict, Any

from iconcommons.logger import Logger

from .storage import AccountPartFlag
from ..base.address import Address
from ..icx.coin_part import CoinPartFlag

Expand Down Expand Up @@ -126,8 +126,8 @@ def run(self, context: 'IconScoreContext'):

for target in self._targets:
address = target.address
coin_part = storage.get_coin_part(context, address)
stake_part = storage.get_stake_part(context, address)
coin_part = storage.get_part(context, AccountPartFlag.COIN, address)
stake_part = storage.get_part(context, AccountPartFlag.STAKE, address)

result: Result = self._check_removable(coin_part, stake_part, target)
if result == Result.FALSE:
Expand Down
122 changes: 122 additions & 0 deletions tests/integrate_test/iiss/decentralized/test_debug_get_acount.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,122 @@
# -*- coding: utf-8 -*-

# Copyright 2018 ICON Foundation
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

"""IconScoreEngine testcase
"""
from unittest.mock import Mock

from iconservice.base.address import SYSTEM_SCORE_ADDRESS
from iconservice.icon_constant import Revision, ICX_IN_LOOP
from iconservice.icx.storage import AccountPartFlag
from iconservice.iiss import IISSMethod
from iconservice.iiss.reward_calc.ipc.reward_calc_proxy import RewardCalcProxy
from tests.integrate_test.iiss.test_iiss_base import TestIISSBase


class TestIISS(TestIISSBase):
def test_debug_get_account_coin(self):
self.update_governance()

# set Revision REV_IISS
self.set_revision(Revision.IISS.value)

expected_ret = {
'coin': {
'type': 0,
'typeStr': 'GENERAL',
'flag': 0,
'flagStr': 'CoinPartFlag.NONE',
'balance': 0
}
}
ret: dict = self.debug_get_account(
self._accounts[0],
account_filter=AccountPartFlag.COIN.value
)
self.assertEqual(expected_ret, ret)

def test_debug_get_account_stake(self):
self.update_governance()

# set Revision REV_IISS
self.set_revision(Revision.IISS.value)

expected_ret = {
'stake': {
'stake': 0,
'unstake': 0,
'unstakeBlockHeight': 0,
'unstakesInfo': []
}
}
ret: dict = self.debug_get_account(
self._accounts[0],
account_filter=AccountPartFlag.STAKE.value
)
self.assertEqual(expected_ret, ret)

def test_debug_get_account_delegation(self):
self.update_governance()

# set Revision REV_IISS
self.set_revision(Revision.IISS.value)

expected_ret = {
'delegation': {
'delegations': [],
'totalDelegated': 0
}
}
ret: dict = self.debug_get_account(
self._accounts[0],
account_filter=AccountPartFlag.DELEGATION.value
)
self.assertEqual(expected_ret, ret)

def test_debug_get_account_all(self):
self.update_governance()

# set Revision REV_IISS
self.set_revision(Revision.IISS.value)

expected_ret = {
'coin': {
'type': 0,
'typeStr': 'GENERAL',
'flag': 0,
'flagStr': 'CoinPartFlag.NONE',
'balance': 0
},
'stake': {
'stake': 0,
'unstake': 0,
'unstakeBlockHeight': 0,
'unstakesInfo': []
},
'delegation': {
'delegations': [],
'totalDelegated': 0
}
}
all_filter: AccountPartFlag = \
AccountPartFlag.COIN | \
AccountPartFlag.STAKE | \
AccountPartFlag.DELEGATION
ret: dict = self.debug_get_account(
self._accounts[0],
account_filter=all_filter.value
)
self.assertEqual(expected_ret, ret)
Loading