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

[4.0] if actions.data & actions.hex_data provided, use the hex_data in api call get_transaction_id #1280

Merged
merged 7 commits into from
Jun 15, 2023
Merged
Show file tree
Hide file tree
Changes from 3 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
44 changes: 44 additions & 0 deletions plugins/chain_api_plugin/chain_api_plugin.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,50 @@ parse_params<chain_apis::read_only::get_transaction_status_params, http_params_t
}
}

// if actions.data & actions.hex_data provided, use the hex_data since only currently support unexploded data
Copy link
Member

Choose a reason for hiding this comment

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

  • As part of this effort, I think we should support exploded data.
  • As part of this effort, I think we should provide optional support for exploded data in cleos. For cleos, this should be optional as a user may want to prevent cleos from communicating with nodeos. Could support the option of providing abi. See --unpack-action-data option --abi-file.
  • To increase security, if both "data" and "hex_data" are provide then we should verify they are equivalent.
  • Please add some tests.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I added a separate issue to include exploded data handling improvements:
#1282

template<>
chain_apis::read_only::get_transaction_id_params
parse_params<chain_apis::read_only::get_transaction_id_params, http_params_types::params_required>(const std::string& body) {
if (body.empty()) {
EOS_THROW(chain::invalid_http_request, "A Request body is required");
}
greg7mdp marked this conversation as resolved.
Show resolved Hide resolved

try {
fc::variant trx_var = fc::json::from_string( body );
Copy link
Contributor

@greg7mdp greg7mdp Jun 14, 2023

Choose a reason for hiding this comment

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

Is it an issue that we don't use a yield function to limit the time spent in the deserialization? never mind!

if( trx_var.is_object() ) {
fc::variant_object& vo = trx_var.get_object();
if( vo.contains("actions") && vo["actions"].is_array() ) {
fc::mutable_variant_object mvo = vo;
fc::variants& action_variants = mvo["actions"].get_array();
for( auto& action_v : action_variants ) {
if( action_v.is_object() ) {
greg7mdp marked this conversation as resolved.
Show resolved Hide resolved
fc::variant_object& action_vo = action_v.get_object();
if( action_vo.contains( "data" ) && action_vo.contains( "hex_data" ) ) {
fc::mutable_variant_object maction_vo = action_vo;
maction_vo["data"] = maction_vo["hex_data"];
action_vo = maction_vo;
vo = mvo;
}
}
}
}
else {
EOS_THROW(chain::invalid_http_request, "Transaction actions are missing or invalid");
heifner marked this conversation as resolved.
Show resolved Hide resolved
}
}
else {
throw false; // invalid transaction
}
auto trx = trx_var.as<chain_apis::read_only::get_transaction_id_params>();
if( trx.id() == transaction().id() ) {
throw false; // invalid transaction
heifner marked this conversation as resolved.
Show resolved Hide resolved
}
return trx;
} catch( ... ) {
EOS_THROW(chain::invalid_http_request, "Invalid transaction");
}
}

#define CALL_WITH_400(api_name, api_handle, api_namespace, call_name, http_response_code, params_type) \
{std::string("/v1/" #api_name "/" #call_name), \
[api_handle](string&&, string&& body, url_response_callback&& cb) mutable { \
Expand Down
46 changes: 46 additions & 0 deletions tests/plugin_http_api_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -600,6 +600,35 @@ def test_ChainApi(self) :
ret_json = self.nodeos.processUrllibRequest(resource, command, self.http_post_invalid_param)
self.assertEqual(ret_json["code"], 400)
self.assertEqual(ret_json["error"]["code"], 3200006)
# get_transaction_id with missing actions
payload_no_actions = {"expiration":"2020-08-01T07:15:49",
"ref_block_num": 34881,
"ref_block_prefix":2972818865,
"max_net_usage_words":0,
"max_cpu_usage_ms":0,
"delay_sec":0,
"context_free_actions":[],
"transaction_extensions": [],
"signatures": ["SIG_K1_KeqfqiZu1GwUxQb7jzK9Fdks6HFaVBQ9AJtCZZj56eG9qGgvVMVtx8EerBdnzrhFoX437sgwtojf2gfz6S516Ty7c22oEp"],
"context_free_data": []}
ret_json = self.nodeos.processUrllibRequest(resource, command, payload_no_actions)
self.assertEqual(ret_json["code"], 400)
self.assertEqual(ret_json["error"]["code"], 3200006)
# get_transaction_id with invalid actions
payload_invalid_actions = {"expiration":"2020-08-01T07:15:49",
"ref_block_num": 34881,
"ref_block_prefix":2972818865,
"max_net_usage_words":0,
"max_cpu_usage_ms":0,
"delay_sec":0,
"context_free_actions":[],
"actions": "hello_world",
"transaction_extensions": [],
"signatures": ["SIG_K1_KeqfqiZu1GwUxQb7jzK9Fdks6HFaVBQ9AJtCZZj56eG9qGgvVMVtx8EerBdnzrhFoX437sgwtojf2gfz6S516Ty7c22oEp"],
"context_free_data": []}
ret_json = self.nodeos.processUrllibRequest(resource, command, payload_invalid_actions)
self.assertEqual(ret_json["code"], 400)
self.assertEqual(ret_json["error"]["code"], 3200006)
# get_transaction_id with valid parameter
payload = {"expiration":"2020-08-01T07:15:49",
"ref_block_num": 34881,
Expand All @@ -614,6 +643,23 @@ def test_ChainApi(self) :
"context_free_data": []}
ret_str = self.nodeos.processUrllibRequest(resource, command, payload, returnType=ReturnType.raw).decode('ascii')
self.assertEqual(ret_str, "\"0be762a6406bab15530e87f21e02d1c58e77944ee55779a76f4112e3b65cac48\"")
# transaction that has hex_data
payload_hex = {"expiration":"2020-08-01T07:15:49",
"ref_block_num": 34881,
"ref_block_prefix":2972818865,
"max_net_usage_words":0,
"max_cpu_usage_ms":0,
"delay_sec":0,
"context_free_actions":[],
"actions":[{"account":"eosio.token","name": "transfer","authorization": [{"actor": "han","permission": "active"}],
"data": "{\"entry\":774831,\"miner\":\"eosminer1111\",\"nonce\":139429}\"}",
"hex_data": "000000000000a6690000000000ea305501000000000000000453595300000000016d"}],
"transaction_extensions": [],
"signatures": ["SIG_K1_KeqfqiZu1GwUxQb7jzK9Fdks6HFaVBQ9AJtCZZj56eG9qGgvVMVtx8EerBdnzrhFoX437sgwtojf2gfz6S516Ty7c22oEp"],
"context_free_data": []}
ret_str = self.nodeos.processUrllibRequest(resource, command, payload_hex, returnType=ReturnType.raw).decode('ascii')
self.assertEqual(ret_str, "\"0be762a6406bab15530e87f21e02d1c58e77944ee55779a76f4112e3b65cac48\"")


# push_block with empty parameter
command = "push_block"
Expand Down
2 changes: 1 addition & 1 deletion tests/read_only_trx_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -265,7 +265,7 @@ def chainApiTests():
runReadOnlyTrxAndRpcInParallel("chain", "get_currency_balance", code=200, payload = {"code":"eosio.token", "account":testAccountName})
runReadOnlyTrxAndRpcInParallel("chain", "get_currency_stats", fieldIn="SYS", payload = {"code":"eosio.token", "symbol":"SYS"})
runReadOnlyTrxAndRpcInParallel("chain", "get_required_keys", code=400)
runReadOnlyTrxAndRpcInParallel("chain", "get_transaction_id", code=200, payload = {"ref_block_num":"1"})
runReadOnlyTrxAndRpcInParallel("chain", "get_transaction_id", code=400, payload = {"ref_block_num":"1"})
runReadOnlyTrxAndRpcInParallel("chain", "push_block", code=202, payload = {"block":"signed_block"})
runReadOnlyTrxAndRpcInParallel("chain", "get_producer_schedule", "active")
runReadOnlyTrxAndRpcInParallel("chain", "get_scheduled_transactions", "transactions", payload = {"json":"true","lower_bound":""})
Expand Down