diff --git a/CHANGELOG.rst b/CHANGELOG.rst index 2146411d6..c729c4639 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -5,6 +5,7 @@ All notable changes to this project are documented in this file. [0.8.3-dev] in progress ----------------------- +- Update ``getassetstate`` RPC method; add ``showallassets`` LevelDBBlockchain function; update prompt.py ``help``, ``show_asset_state``, and ``show_contract_state`` - Disallow ``Void`` type input parameters for smart contracts and increase test coverage - Fix confirmed tx not being purged from mempool `#703 `_ - Fix bootstrap thread joining failure on Ubuntu systems diff --git a/neo/Implementations/Blockchains/LevelDB/LevelDBBlockchain.py b/neo/Implementations/Blockchains/LevelDB/LevelDBBlockchain.py index c46ed96e0..33732f80b 100644 --- a/neo/Implementations/Blockchains/LevelDB/LevelDBBlockchain.py +++ b/neo/Implementations/Blockchains/LevelDB/LevelDBBlockchain.py @@ -340,6 +340,12 @@ def SearchAssetState(self, query): assets = DBCollection(self._db, DBPrefix.ST_Asset, AssetState) keys = assets.Keys + if query.lower() == "neo": + query = "AntShare" + + if query.lower() in {"gas", "neogas"}: + query = "AntCoin" + for item in keys: asset = assets.TryGet(keyval=item) if query in asset.Name.decode('utf-8'): @@ -365,6 +371,12 @@ def GetAssetState(self, assetId): return asset + def ShowAllAssets(self): + + assets = DBCollection(self._db, DBPrefix.ST_Asset, AssetState) + keys = assets.Keys + return keys + def GetTransaction(self, hash): if type(hash) is str: diff --git a/neo/Implementations/Blockchains/LevelDB/test_LevelDBBlockchain.py b/neo/Implementations/Blockchains/LevelDB/test_LevelDBBlockchain.py index 320bef8ae..84baee683 100644 --- a/neo/Implementations/Blockchains/LevelDB/test_LevelDBBlockchain.py +++ b/neo/Implementations/Blockchains/LevelDB/test_LevelDBBlockchain.py @@ -74,3 +74,7 @@ def test_GetHeaderBy(self): invalid_bc_height = self._blockchain.Height + 1 block = self._blockchain.GetHeaderBy(invalid_bc_height) self.assertEqual(block, None) + + def test_ShowAllAssets(self): + assets = Blockchain.Default().ShowAllAssets() + self.assertEqual(len(assets), 2) diff --git a/neo/api/JSONRPC/JsonRpcApi.py b/neo/api/JSONRPC/JsonRpcApi.py index 391bbcee2..d605090c3 100644 --- a/neo/api/JSONRPC/JsonRpcApi.py +++ b/neo/api/JSONRPC/JsonRpcApi.py @@ -196,8 +196,14 @@ def json_rpc_method_handler(self, method, params): return acct.ToJson() elif method == "getassetstate": - asset_id = UInt256.ParseString(params[0]) - asset = Blockchain.Default().GetAssetState(asset_id.ToBytes()) + asset_str = params[0] + if asset_str.lower() == 'neo': + assetId = Blockchain.Default().SystemShare().Hash + elif asset_str.lower() == 'gas': + assetId = Blockchain.Default().SystemCoin().Hash + else: + assetId = UInt256.ParseString(params[0]) + asset = Blockchain.Default().GetAssetState(assetId.ToBytes()) if asset: return asset.ToJson() raise JsonRpcError(-100, "Unknown asset") diff --git a/neo/api/JSONRPC/test_json_rpc_api.py b/neo/api/JSONRPC/test_json_rpc_api.py index 29fa15d41..4aa5933cc 100644 --- a/neo/api/JSONRPC/test_json_rpc_api.py +++ b/neo/api/JSONRPC/test_json_rpc_api.py @@ -222,7 +222,7 @@ def test_account_state_failure(self): self.assertEqual(-2146233033, res['error']['code']) self.assertEqual('One of the identified items was in an invalid format.', res['error']['message']) - def test_get_asset_state(self): + def test_get_asset_state_hash(self): asset_str = '602c79718b16e442de58778e148d0b1084e3b2dffd5de6b7b16cee7969282de7' req = self._gen_post_rpc_req("getassetstate", params=[asset_str]) mock_req = mock_post_request(json.dumps(req).encode("utf-8")) @@ -231,6 +231,24 @@ def test_get_asset_state(self): self.assertEqual(res['result']['admin'], 'AWKECj9RD8rS8RPcpCgYVjk1DeYyHwxZm3') self.assertEqual(res['result']['available'], 0) + def test_get_asset_state_neo(self): + asset_str = 'neo' + req = self._gen_post_rpc_req("getassetstate", params=[asset_str]) + mock_req = mock_post_request(json.dumps(req).encode("utf-8")) + res = json.loads(self.app.home(mock_req)) + self.assertEqual(res['result']['assetId'], '0x%s' % str(GetBlockchain().SystemShare().Hash)) + self.assertEqual(res['result']['admin'], 'Abf2qMs1pzQb8kYk9RuxtUb9jtRKJVuBJt') + self.assertEqual(res['result']['available'], 10000000000000000) + + def test_get_asset_state_gas(self): + asset_str = 'GAS' + req = self._gen_post_rpc_req("getassetstate", params=[asset_str]) + mock_req = mock_post_request(json.dumps(req).encode("utf-8")) + res = json.loads(self.app.home(mock_req)) + self.assertEqual(res['result']['assetId'], '0x%s' % str(GetBlockchain().SystemCoin().Hash)) + self.assertEqual(res['result']['amount'], 10000000000000000) + self.assertEqual(res['result']['admin'], 'AWKECj9RD8rS8RPcpCgYVjk1DeYyHwxZm3') + def test_get_asset_state_0x(self): asset_str = '0x602c79718b16e442de58778e148d0b1084e3b2dffd5de6b7b16cee7969282de7' req = self._gen_post_rpc_req("getassetstate", params=[asset_str]) diff --git a/neo/bin/prompt.py b/neo/bin/prompt.py index d2cccd6e6..69a344dc3 100755 --- a/neo/bin/prompt.py +++ b/neo/bin/prompt.py @@ -43,6 +43,7 @@ from neo.UserPreferences import preferences from neocore.KeyPair import KeyPair from neocore.UInt256 import UInt256 +from neocore.UInt160 import UInt160 from neo.logging import log_manager logger = log_manager.getLogger() @@ -99,8 +100,10 @@ class PromptInterface: 'tx {hash}', 'account {address} # returns account state', 'asset {assetId} # returns asset state', + 'asset all # returns a list of all assets', 'asset search {query}', 'contract {contract hash} # returns contract state', + 'contract all # returns a list of all contracts', 'contract search {query}', 'notifications {block_number or address}', 'mem # returns memory in use and number of buffers', @@ -675,7 +678,20 @@ def show_asset_state(self, args): if item is not None: - if item == 'search': + if item.lower() == 'all': + assets = Blockchain.Default().ShowAllAssets() + assetlist = [] + for asset in assets: + state = Blockchain.Default().GetAssetState(asset.decode('utf-8')).ToJson() + asset_dict = {state['name']: state['assetId']} + assetlist.append(asset_dict) + bjson = json.dumps(assetlist, indent=4) + tokens = [("class:number", bjson)] + print_formatted_text(FormattedText(tokens), style=self.token_style) + print('\n') + return + + elif item.lower() == 'search': query = get_arg(args, 1) results = Blockchain.Default().SearchAssetState(query) print("Found %s results for %s" % (len(results), query)) @@ -684,10 +700,20 @@ def show_asset_state(self, args): tokens = [("class:number", bjson)] print_formatted_text(FormattedText(tokens), style=self.token_style) print('\n') - return - asset = Blockchain.Default().GetAssetState(item) + if item.lower() == 'neo': + assetId = Blockchain.Default().SystemShare().Hash + elif item.lower() == 'gas': + assetId = Blockchain.Default().SystemCoin().Hash + else: + try: + assetId = UInt256.ParseString(item) + except Exception: + print("Could not find asset from args: %s" % args) + return + + asset = Blockchain.Default().GetAssetState(assetId.ToBytes()) if asset is not None: bjson = json.dumps(asset.ToJson(), indent=4) @@ -706,7 +732,17 @@ def show_contract_state(self, args): if item.lower() == 'all': contracts = Blockchain.Default().ShowAllContracts() - print("Contracts: %s" % contracts) + contractlist = [] + for contract in contracts: + state = Blockchain.Default().GetContract(contract.decode('utf-8')).ToJson() + contract_dict = {state['name']: state['hash']} + contractlist.append(contract_dict) + bjson = json.dumps(contractlist, indent=4) + tokens = [("class:number", bjson)] + print_formatted_text(FormattedText(tokens), style=self.token_style) + print('\n') + return + elif item.lower() == 'search': query = get_arg(args, 1) if query: @@ -721,7 +757,13 @@ def show_contract_state(self, args): else: print("Please specify a search query") else: - contract = Blockchain.Default().GetContract(item) + try: + hash = UInt160.ParseString(item).ToBytes() + except Exception: + print("Could not find contract from args: %s" % args) + return + + contract = Blockchain.Default().GetContract(hash) if contract is not None: contract.DetermineIsNEP5()