aboutsummaryrefslogtreecommitdiff
path: root/src/cryptonote_core
diff options
context:
space:
mode:
authormoneromooo-monero <moneromooo-monero@users.noreply.github.com>2016-09-26 23:11:10 +0100
committermoneromooo-monero <moneromooo-monero@users.noreply.github.com>2016-09-27 07:46:39 +0100
commitbba6af9064cb95596039f5a8f7ea460d3dedef0d (patch)
treead28f318cff63d547eedb11d81ae3b4ffac7aeb6 /src/cryptonote_core
parentwallet: fix log confusion between bytes and kilobytes (diff)
downloadmonero-bba6af9064cb95596039f5a8f7ea460d3dedef0d.tar.xz
wallet: cold wallet transaction signing
This change adds the ability to create a new unsigned transaction from a watch only wallet, and save it to a file. This file can then be moved to another computer/VM where a cold wallet may load it, sign it, and save it. That cold wallet does not need to have a blockchain nor daemon. The signed transaction file can then be moved back to the watch only wallet, which can load it and send it to the daemon. Two new simplewallet commands to use it: sign_transfer (on the cold wallet) submit_transfer (on the watch only wallet) The transfer command used on a watch only wallet now writes an unsigned transaction set in a file called 'unsigned_monero_tx' instead of submitting the tx to the daemon as a normal wallet does. The signed tx file is called 'signed_monero_tx'.
Diffstat (limited to 'src/cryptonote_core')
-rw-r--r--src/cryptonote_core/cryptonote_format_utils.cpp16
-rw-r--r--src/cryptonote_core/cryptonote_format_utils.h15
2 files changed, 26 insertions, 5 deletions
diff --git a/src/cryptonote_core/cryptonote_format_utils.cpp b/src/cryptonote_core/cryptonote_format_utils.cpp
index 7e0c75ccf..64f8eb924 100644
--- a/src/cryptonote_core/cryptonote_format_utils.cpp
+++ b/src/cryptonote_core/cryptonote_format_utils.cpp
@@ -472,10 +472,7 @@ namespace cryptonote
bool construct_tx_and_get_tx_key(const account_keys& sender_account_keys, const std::vector<tx_source_entry>& sources, const std::vector<tx_destination_entry>& destinations, std::vector<uint8_t> extra, transaction& tx, uint64_t unlock_time, crypto::secret_key &tx_key, bool rct)
{
std::vector<rct::key> amount_keys;
- tx.vin.clear();
- tx.vout.clear();
- tx.signatures.clear();
- tx.rct_signatures.type = rct::RCTTypeNull;
+ tx.set_null();
amount_keys.clear();
tx.version = rct ? 2 : 1;
@@ -615,6 +612,14 @@ namespace cryptonote
return false;
}
+ // check for watch only wallet
+ bool zero_secret_key = true;
+ for (size_t i = 0; i < sizeof(sender_account_keys.m_spend_secret_key); ++i)
+ zero_secret_key &= (sender_account_keys.m_spend_secret_key.data[i] == 0);
+ if (zero_secret_key)
+ {
+ LOG_PRINT_L1("Null secret key, skipping signatures");
+ }
if (tx.version == 1)
{
@@ -641,7 +646,8 @@ namespace cryptonote
tx.signatures.push_back(std::vector<crypto::signature>());
std::vector<crypto::signature>& sigs = tx.signatures.back();
sigs.resize(src_entr.outputs.size());
- crypto::generate_ring_signature(tx_prefix_hash, boost::get<txin_to_key>(tx.vin[i]).k_image, keys_ptrs, in_contexts[i].in_ephemeral.sec, src_entr.real_output, sigs.data());
+ if (!zero_secret_key)
+ crypto::generate_ring_signature(tx_prefix_hash, boost::get<txin_to_key>(tx.vin[i]).k_image, keys_ptrs, in_contexts[i].in_ephemeral.sec, src_entr.real_output, sigs.data());
ss_ring_s << "signatures:" << ENDL;
std::for_each(sigs.begin(), sigs.end(), [&](const crypto::signature& s){ss_ring_s << s << ENDL;});
ss_ring_s << "prefix_hash:" << tx_prefix_hash << ENDL << "in_ephemeral_key: " << in_contexts[i].in_ephemeral.sec << ENDL << "real_output: " << src_entr.real_output;
diff --git a/src/cryptonote_core/cryptonote_format_utils.h b/src/cryptonote_core/cryptonote_format_utils.h
index a42296994..24db8008e 100644
--- a/src/cryptonote_core/cryptonote_format_utils.h
+++ b/src/cryptonote_core/cryptonote_format_utils.h
@@ -62,6 +62,16 @@ namespace cryptonote
rct::key mask; //ringct amount mask
void push_output(uint64_t idx, const crypto::public_key &k, uint64_t amount) { outputs.push_back(std::make_pair(idx, rct::ctkey({rct::pk2rct(k), rct::zeroCommit(amount)}))); }
+
+ BEGIN_SERIALIZE_OBJECT()
+ FIELD(outputs)
+ VARINT_FIELD(real_output)
+ FIELD(real_out_tx_key)
+ VARINT_FIELD(real_output_in_tx_index)
+ VARINT_FIELD(amount)
+ FIELD(rct)
+ FIELD(mask)
+ END_SERIALIZE()
};
struct tx_destination_entry
@@ -71,6 +81,11 @@ namespace cryptonote
tx_destination_entry() : amount(0), addr(AUTO_VAL_INIT(addr)) { }
tx_destination_entry(uint64_t a, const account_public_address &ad) : amount(a), addr(ad) { }
+
+ BEGIN_SERIALIZE_OBJECT()
+ VARINT_FIELD(amount)
+ FIELD(addr)
+ END_SERIALIZE()
};
//---------------------------------------------------------------