diff --git a/programs/cleos/main.cpp b/programs/cleos/main.cpp index 3ea631ab6f9..f2fd1e1f13c 100644 --- a/programs/cleos/main.cpp +++ b/programs/cleos/main.cpp @@ -3781,6 +3781,23 @@ int main( int argc, char** argv ) { EOSC_ASSERT( str_private_key.empty() || str_public_key.empty(), "ERROR: Either -k/--private-key or --public-key or none of them can be set" ); fc::variant trx_var = json_from_file_or_string(trx_json_to_sign); + + // If transaction was packed, unpack it before signing + bool was_packed_trx = false; + if( trx_var.is_object() ) { + fc::variant_object& vo = trx_var.get_object(); + if( vo.contains("packed_trx") ) { + packed_transaction_v0 packed_trx; + try { + fc::from_variant( trx_var, packed_trx ); + } EOS_RETHROW_EXCEPTIONS( transaction_type_exception, "Invalid packed transaction format: '${data}'", + ("data", fc::json::to_string(trx_var, fc::time_point::maximum()))) + const signed_transaction& strx = packed_trx.get_signed_transaction(); + trx_var = strx; + was_packed_trx = true; + } + } + signed_transaction trx; try { abi_serializer::from_variant( trx_var, trx, abi_serializer_resolver_empty, abi_serializer::create_yield_function( abi_serializer_max_time ) ); @@ -3822,7 +3839,11 @@ int main( int argc, char** argv ) { auto trx_result = call(push_txn_func, packed_transaction_v0(trx, packed_transaction_v0::compression_type::none)); std::cout << fc::json::to_pretty_string(trx_result) << std::endl; } else { - std::cout << fc::json::to_pretty_string(trx) << std::endl; + if ( was_packed_trx ) { // pack it as before + std::cout << fc::json::to_pretty_string(packed_transaction_v0(trx,packed_transaction_v0::compression_type::none)) << std::endl; + } else { + std::cout << fc::json::to_pretty_string(trx) << std::endl; + } } }); diff --git a/tests/cli_test.py b/tests/cli_test.py index 354c32695e7..e0b384501ae 100755 --- a/tests/cli_test.py +++ b/tests/cli_test.py @@ -56,6 +56,79 @@ def cli11_optional_option_arg_test(): '-c', chain, '-k', key, '{}']) assert(b'signatures' in output) +def cleos_sign_test(): + """Test that sign can on both regular and packed transactions""" + chain = 'cf057bbfb72640471fd910bcb67639c22df9f92470936cddc1ade0e2f2e7dc4f' + key = '5Jgfqh3svgBZvCAQkcnUX8sKmVUkaUekYDGqFakm52Ttkc5MBA4' + + # regular trasaction + trx = ( + '{' + '"expiration": "2019-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": "eosio",' + '"permission": "active"' + '}' + '],' + '"data": "000000000000a6690000000000ea305501000000000000000453595300000000016d"' + '}' + '],' + '"transaction_extensions": [],' + '"context_free_data": []' + '}') + + output = subprocess.check_output(['./programs/cleos/cleos', 'sign', + '-c', chain, '-k', key, trx]) + # make sure it is signed + assert(b'signatures' in output) + # make sure fields are kept + assert(b'"expiration": "2019-08-01T07:15:49"' in output) + assert(b'"ref_block_num": 34881' in output) + assert(b'"ref_block_prefix": 2972818865' in output) + assert(b'"account": "eosio.token"' in output) + assert(b'"name": "transfer"' in output) + assert(b'"actor": "eosio"' in output) + assert(b'"permission": "active"' in output) + assert(b'"data": "000000000000a6690000000000ea305501000000000000000453595300000000016d"' in output) + + packed_trx = ' { "signatures": [], "compression": "none", "packed_context_free_data": "", "packed_trx": "a591425d4188b19d31b1000000000100a6823403ea3055000000572d3ccdcd010000000000ea305500000000a8ed323222000000000000a6690000000000ea305501000000000000000453595300000000016d00" } ' + + # Test packed transaction is unpacked. Only with options --print-request and --public-key + # the sign request is dumped to stderr. + cmd = ['./programs/cleos/cleos', '--print-request', 'sign', '-c', chain, '--public-key', 'EOS8Dq1KosJ9PMn1vKQK3TbiihgfUiDBUsz471xaCE6eYUssPB1KY', packed_trx] + outs=None + errs=None + try: + popen=subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE) + outs,errs=popen.communicate() + popen.wait() + except subprocess.CalledProcessError as ex: + print(ex.output) + # make sure fields are unpacked + assert(b'"expiration": "2019-08-01T07:15:49"' in errs) + assert(b'"ref_block_num": 34881' in errs) + assert(b'"ref_block_prefix": 2972818865' in errs) + assert(b'"account": "eosio.token"' in errs) + assert(b'"name": "transfer"' in errs) + assert(b'"actor": "eosio"' in errs) + assert(b'"permission": "active"' in errs) + assert(b'"data": "000000000000a6690000000000ea305501000000000000000453595300000000016d"' in errs) + + # Test packed transaction is signed. + output = subprocess.check_output(['./programs/cleos/cleos', 'sign', + '-c', chain, '-k', key, packed_trx]) + # Make sure signatures not empty + assert(b'signatures' in output) + assert(b'"signatures": []' not in output) nodeos_help_test() @@ -67,3 +140,4 @@ def cli11_optional_option_arg_test(): cli11_bugfix_test() cli11_optional_option_arg_test() +cleos_sign_test()