CityOfZion / neo-python

Python Node and SDK for the NEO 2.x blockchain. For NEO 3.x go to our successor project neo-mamba
https://neo-python.readthedocs.io/en/latest/
MIT License
313 stars 189 forks source link

Parser breaks when reading --tx-attr argument with spaces #1009

Open hal0x2328 opened 5 years ago

hal0x2328 commented 5 years ago

Current behavior

Using --tx-attrs with any spaces inside the attribute JSON (even inside quoted strings) results in the following error:

[E 190822 14:50:54 Utils:197] Could not parse json from tx attrs: unexpected EOF while parsing (<string>, line 1) 

Expected behavior

To properly parse tx attributes with spaces in them

How to reproduce

Try the following invocation on TestNet - the --tx-attr value is taken directly from the example shown by the sc invoke help command in np-prompt:

sc invoke 9aff1e08aea2048a26a3d2ddbb3df495b932b1e7 transfer ['AaPoixMs8SAd7
XtXzJqt1t7MsKwjY6KaiL','Ae8JQr7b9QtCxcQMjJSbxAv685UqWF8CY7',100000000000] --tx-a
ttr=[{"usage": 0x90,"data":"my brief description"}]       

The spaces both inside and outside of the quotes will stop the parser from reading the rest of the string, resulting in the EOF error. This works:

--tx-attr=[{"usage":0x90,"data":"my_brief_description"}] 

but it's not ideal for text remarks to be unable to have spaces in them. I tried escaping the spaces with one or more backslashes to no avail. The only way to get the attribute accepted is to remove all spaces inside and outside of the quotes.

Your environment

jseagrave21 commented 5 years ago

@hal0x2328 I am having trouble recreating your error. I changed the attribute unittests in test_send_commands.py to:

def test_attributes(self):
        nodemgr = NodeManager()
        nodemgr.reset_for_test()
        nodemgr.nodes = [NeoNode(object, object)]

        with patch('neo.Network.node.NeoNode.relay', return_value=self.async_return(True)):
            with patch('neo.Prompt.Commands.Send.prompt', side_effect=[UserWalletTestCase.wallet_1_pass()]):
                PromptData.Wallet = self.GetWallet1(recreate=True)
                args = ['send', 'gas', self.watch_addr_str, '2', '--tx-attr={"usage": 241,"data":"This is a remark"}']

                res = Wallet.CommandWallet().execute(args)
                for item in res.Attributes:
                    print(item.ToJson())
                self.assertTrue(res)
                self.assertEqual(2, len(
                    res.Attributes))  # By default the script_hash of the transaction sender is added to the TransactionAttribute list, therefore the Attributes length is `count` + 1

    def test_multiple_attributes(self):
        nodemgr = NodeManager()
        nodemgr.reset_for_test()
        nodemgr.nodes = [NeoNode(object, object)]

        with patch('neo.Network.node.NeoNode.relay', return_value=self.async_return(True)):
            with patch('neo.Prompt.Commands.Send.prompt', side_effect=[UserWalletTestCase.wallet_1_pass()]):
                PromptData.Wallet = self.GetWallet1(recreate=True)
                args = ['send', 'gas', self.watch_addr_str, '2',
                        '--tx-attr=[{"usage": 0x90,"data":"my brief description"}, {"usage":242,"data":"This is a remark 2"}]']

                res = Wallet.CommandWallet().execute(args)
                for item in res.Attributes:
                    print(item.ToJson())
                self.assertTrue(res)
                self.assertEqual(3, len(res.Attributes))

and got these results:

test_attributes (neo.Prompt.Commands.tests.test_send_commands.UserWalletTestCase) ... Sending with fee: 0
Validate your transaction details
---------------------------------
Sending 2 GAS from AJQ6FoaSXDFzA6wLnyZ1nFN7SGSN2oNTc3 to AGYaEi3W6ndHPUmW7T12FFfsbQ6DWymkEm
Returning 11.9998 GAS as change to AJQ6FoaSXDFzA6wLnyZ1nFN7SGSN2oNTc3

Enter your password to send to the network
Relayed Tx: 9b8af67d09ee01b2d877e9c63e91fed18b6903574444c953f97cc2184f68925f
{'usage': 32, 'data': '1cc9c05cefffe6cdd7b182816a9152ec218d2ec0'}
{'usage': 241, 'data': '5468697320697320612072656d61726b'}
ok

and

test_multiple_attributes (neo.Prompt.Commands.tests.test_send_commands.UserWalletTestCase) ... Sending with fee: 0
Validate your transaction details
---------------------------------
Sending 2 GAS from AJQ6FoaSXDFzA6wLnyZ1nFN7SGSN2oNTc3 to AGYaEi3W6ndHPUmW7T12FFfsbQ6DWymkEm
Returning 11.9998 GAS as change to AJQ6FoaSXDFzA6wLnyZ1nFN7SGSN2oNTc3

Enter your password to send to the network
Relayed Tx: 7ec898be6eb4ecd4b9969b3c69c804332fc7ed4195ab562089ce03aaa6f67d9a
{'usage': 32, 'data': '1cc9c05cefffe6cdd7b182816a9152ec218d2ec0'}
{'usage': 144, 'data': '6d79206272696566206465736372697074696f6e'}
{'usage': 242, 'data': '5468697320697320612072656d61726b2032'}
ok

I will let you know if I see something different from within prompt once I can get a privatenet spun up.

jseagrave21 commented 5 years ago

@hal0x2328 I confirmed the behavior and am pushing a possible solution now

jseagrave21 commented 4 years ago

@hal0x2328 could you confirm this issue is resolved?