From a4a57439071fe62021d535c45c11035c0e6539fa Mon Sep 17 00:00:00 2001 From: Erik van den Brink Date: Sat, 27 Jan 2018 19:15:43 +0100 Subject: [PATCH 1/2] Add 'gettxout' rpc call + tests --- .../Blockchains/LevelDB/LevelDBBlockchain.py | 2 +- neo/api/JSONRPC/JsonRpcApi.py | 8 +++- neo/api/JSONRPC/test_json_rpc_api.py | 39 +++++++++++++++++++ 3 files changed, 47 insertions(+), 2 deletions(-) diff --git a/neo/Implementations/Blockchains/LevelDB/LevelDBBlockchain.py b/neo/Implementations/Blockchains/LevelDB/LevelDBBlockchain.py index c7cfc8a70..5d1b37cf2 100644 --- a/neo/Implementations/Blockchains/LevelDB/LevelDBBlockchain.py +++ b/neo/Implementations/Blockchains/LevelDB/LevelDBBlockchain.py @@ -262,7 +262,7 @@ def GetAllSpentCoins(self): def GetUnspent(self, hash, index): sn = self._db.snapshot() - coins = DBCollection(self._db, sn, DBPrefix.ST_SpentCoin, UnspentCoinState) + coins = DBCollection(self._db, sn, DBPrefix.ST_Coin, UnspentCoinState) state = coins.TryGet(hash) diff --git a/neo/api/JSONRPC/JsonRpcApi.py b/neo/api/JSONRPC/JsonRpcApi.py index ad3a2dbad..a01a37663 100644 --- a/neo/api/JSONRPC/JsonRpcApi.py +++ b/neo/api/JSONRPC/JsonRpcApi.py @@ -201,7 +201,13 @@ def json_rpc_method_handler(self, method, params): return None elif method == "gettxout": - raise NotImplementedError() + hash = params[0].encode('utf-8') + index = params[1] + utxo = Blockchain.Default().GetUnspent(hash, index) + if utxo: + return utxo.ToJson(index) + else: + return None elif method == "invoke": shash = UInt160.ParseString(params[0]) diff --git a/neo/api/JSONRPC/test_json_rpc_api.py b/neo/api/JSONRPC/test_json_rpc_api.py index 908c01f4a..4e7b9929e 100644 --- a/neo/api/JSONRPC/test_json_rpc_api.py +++ b/neo/api/JSONRPC/test_json_rpc_api.py @@ -347,3 +347,42 @@ def test_get_unspents(self): u = UInt256.ParseString('0ff23561c611ccda65470c9a4a5f1be31f2f4f61b98c75d051e1a72e85a302eb') unspents = GetBlockchain().GetAllUnspent(u) self.assertEqual(len(unspents), 1) + + def test_gettxout(self): + # block 730901 - 2 transactions + # output with index 0 is spent, so should return an error + + txid = '0ff23561c611ccda65470c9a4a5f1be31f2f4f61b98c75d051e1a72e85a302eb' + output_index = 0 + req = self._gen_rpc_req("gettxout", params=[txid, output_index]) + mock_req = mock_request(json.dumps(req).encode("utf-8")) + res = json.loads(self.app.home(mock_req)) + # will return `null` if not found + self.assertEqual(None, res["result"]) + + # output with index 1 is unspent, so should return valid values + txid = '0ff23561c611ccda65470c9a4a5f1be31f2f4f61b98c75d051e1a72e85a302eb' + output_index = 1 + req = self._gen_rpc_req("gettxout", params=[txid, output_index]) + mock_req = mock_request(json.dumps(req).encode("utf-8")) + res = json.loads(self.app.home(mock_req)) + + expected_asset = '0x602c79718b16e442de58778e148d0b1084e3b2dffd5de6b7b16cee7969282de7' + expected_value = "25" + expected_address = 'AHYb3ySrHbhzouZ81ZMnCf8c7zYaoDg64x' + + self.assertEqual(output_index, res["result"]["n"]) + self.assertEqual(expected_address, res["result"]["address"]) + self.assertEqual(expected_asset, res["result"]["asset"]) + self.assertEqual(expected_value, res["result"]["value"]) + + # now test for a different block (730848) with a floating value + txid = '9c9f2c430c3cfb805e8c22d0a7778a60ce7792fad52ffe9b34f56de8e2c1d2e6' + output_index = 1 # index 0 is spent, 0 is unspent + req = self._gen_rpc_req("gettxout", params=[txid, output_index]) + mock_req = mock_request(json.dumps(req).encode("utf-8")) + res = json.loads(self.app.home(mock_req)) + + expected_value = "2609.997813" + self.assertEqual(output_index, res["result"]["n"]) + self.assertEqual(expected_value, res["result"]["value"]) From 81b8fa0ccffd46b01eb31c9c8364864d98549c34 Mon Sep 17 00:00:00 2001 From: Erik van den Brink Date: Sat, 27 Jan 2018 19:16:34 +0100 Subject: [PATCH 2/2] add docs --- neo/api/JSONRPC/neo-cli-json-rpc-docs.md | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/neo/api/JSONRPC/neo-cli-json-rpc-docs.md b/neo/api/JSONRPC/neo-cli-json-rpc-docs.md index 030ecc533..44f8537d4 100644 --- a/neo/api/JSONRPC/neo-cli-json-rpc-docs.md +++ b/neo/api/JSONRPC/neo-cli-json-rpc-docs.md @@ -38,3 +38,16 @@ On MainNet there are actually entries, each of which has this format: `0xde3bc1d curl -X POST http://seed2.neo.org:20332 -H 'Content-Type: application/json' -d '{ "jsonrpc": "2.0", "id": 5, "method": "getversion", "params": [] }' { "jsonrpc": "2.0", "id": 5, "result": { "port": 20333, "nonce": 771199013, "useragent": "/NEO:2.6.0/" } } + +## `gettxout` + + curl -X POST http://seed2.neo.org:20332 -H 'Content-Type: application/json' -d '{ "jsonrpc": "2.0", "id": 5, "method": "gettxout", "params": ["0ff23561c611ccda65470c9a4a5f1be31f2f4f61b98c75d051e1a72e85a302eb", 1] }' + {"jsonrpc":"2.0","id":5,"result":{"n":1,"asset":"0x602c79718b16e442de58778e148d0b1084e3b2dffd5de6b7b16cee7969282de7","value":"25","address":"AHYb3ySrHbhzouZ81ZMnCf8c7zYaoDg64x"} + +### secondary unspent showing float "value" vs the above int value + curl -X POST http://seed2.neo.org:20332 -H 'Content-Type: application/json' -d '{ "jsonrpc": "2.0", "id": 5, "method": "gettxout", "params": ["9c9f2c430c3cfb805e8c22d0a7778a60ce7792fad52ffe9b34f56de8e2c1d2e6", 1] }' + {"jsonrpc":"2.0","id":5,"result":{"n":1,"asset":"0x602c79718b16e442de58778e148d0b1084e3b2dffd5de6b7b16cee7969282de7","value":"2609.997813","address":"ASs7BiaRa9Z2NnJfvf7a4SZ7ciPLiPWefJ"}} + +### when querying an already spent output + curl -X POST http://seed2.neo.org:20332 -H 'Content-Type: application/json' -d '{ "jsonrpc": "2.0", "id": 5, "method": "gettxout", "params": ["0ff23561c611ccda65470c9a4a5f1be31f2f4f61b98c75d051e1a72e85a302eb", 0] }' + {"jsonrpc":"2.0","id":5,"result":null} \ No newline at end of file