diff --git a/rai/core_test/rpc.cpp b/rai/core_test/rpc.cpp index 7f7f2883..02845c4c 100644 --- a/rai/core_test/rpc.cpp +++ b/rai/core_test/rpc.cpp @@ -3093,6 +3093,43 @@ TEST (rpc, block_create) ASSERT_EQ (receive_hash, latest.to_string ()); } +TEST (rpc, block_create_utx) +{ + rai::system system (24000, 1); + rai::keypair key; + rai::genesis genesis; + system.wallet (0)->insert_adhoc (rai::test_genesis_key.prv); + boost::property_tree::ptree request; + request.put ("action", "block_create"); + request.put ("type", "utx"); + request.put ("wallet", system.nodes[0]->wallets.items.begin ()->first.to_string ()); + request.put ("account", rai::test_genesis_key.pub.to_account ()); + request.put ("previous", genesis.hash ().to_string ()); + request.put ("representative", rai::test_genesis_key.pub.to_account ()); + request.put ("balance", (rai::genesis_amount - rai::Gxrb_ratio).convert_to ()); + request.put ("link", key.pub.to_account ()); + request.put ("work", rai::to_string_hex (system.nodes[0]->generate_work (genesis.hash ()))); + rai::rpc rpc (system.service, *system.nodes[0], rai::rpc_config (true)); + rpc.start (); + test_response response (request, rpc, system.service); + while (response.status == 0) + { + system.poll (); + } + ASSERT_EQ (200, response.status); + std::string utx_hash (response.json.get ("hash")); + auto utx_text (response.json.get ("block")); + std::stringstream block_stream (utx_text); + boost::property_tree::ptree block_l; + boost::property_tree::read_json (block_stream, block_l); + auto utx_block (rai::deserialize_block_json (block_l)); + ASSERT_NE (nullptr, utx_block); + ASSERT_EQ (rai::block_type::utx, utx_block->type ()); + ASSERT_EQ (utx_hash, utx_block->hash ().to_string ()); + auto process_result (system.nodes[0]->process (*utx_block)); + ASSERT_EQ (rai::process_result::progress, process_result.code); +} + TEST (rpc, wallet_lock) { rai::system system (24000, 1); diff --git a/rai/lib/blocks.cpp b/rai/lib/blocks.cpp index 65bcc14d..908f3604 100644 --- a/rai/lib/blocks.cpp +++ b/rai/lib/blocks.cpp @@ -1175,6 +1175,15 @@ std::unique_ptr rai::deserialize_block_json (boost::property_tree::p result = std::move (obj); } } + else if (type == "utx") + { + bool error; + std::unique_ptr obj (new rai::utx_block (error, tree_a)); + if (!error) + { + result = std::move (obj); + } + } } catch (std::runtime_error const &) { diff --git a/rai/node/rpc.cpp b/rai/node/rpc.cpp index 483ecd4c..285bc657 100644 --- a/rai/node/rpc.cpp +++ b/rai/node/rpc.cpp @@ -1165,6 +1165,7 @@ void rai::rpc_handler::block_create () prv.data.clear (); rai::uint256_union previous (0); rai::uint128_union balance (0); + rai::uint256_union link (0); if (wallet != 0 && account != 0) { auto existing (node.wallets.items.find (wallet)); @@ -1223,11 +1224,37 @@ void rai::rpc_handler::block_create () error_response (response, "Bad balance number"); } } + boost::optional link_text (request.get_optional ("link")); + if (link_text.is_initialized ()) + { + auto error_link (link.decode_account (link_text.get ())); + if (error_link) + { + error_response (response, "Bad link number"); + } + } if (prv.data != 0) { rai::uint256_union pub; ed25519_publickey (prv.data.bytes.data (), pub.bytes.data ()); - if (type == "open") + if (type == "utx") + { + if (!account.is_zero () && !previous.is_zero () && !representative.is_zero () && !balance.is_zero () && link_text.is_initialized ()) + { + rai::utx_block utx (account, previous, representative, balance, link, prv, pub, work); + boost::property_tree::ptree response_l; + response_l.put ("hash", utx.hash ().to_string ()); + std::string contents; + utx.serialize_json (contents); + response_l.put ("block", contents); + response (response_l); + } + else + { + error_response (response, "Account, previous, representative, balance, and link are required"); + } + } + else if (type == "open") { if (representative != 0 && source != 0) {