apply patch from @stoffu for sub-addresses

https://github.com/moneroexamples/onion-monero-blockchain-explorer/pull/86#issuecomment-342997868
This commit is contained in:
moneroexamples 2017-11-09 08:14:18 +08:00
parent 886d2a5749
commit ddc6ef7405
4 changed files with 162 additions and 20 deletions

1
.gitignore vendored
View file

@ -6,4 +6,5 @@
*.log *.log
*.orig *.orig
tests/ tests/
build/
cmake-build-debug/ cmake-build-debug/

View file

@ -126,6 +126,7 @@ namespace xmreg
crypto::hash hash; crypto::hash hash;
crypto::hash prefix_hash; crypto::hash prefix_hash;
crypto::public_key pk; crypto::public_key pk;
std::vector<crypto::public_key> additional_pks;
uint64_t xmr_inputs; uint64_t xmr_inputs;
uint64_t xmr_outputs; uint64_t xmr_outputs;
uint64_t num_nonrct_inputs; uint64_t num_nonrct_inputs;
@ -1469,11 +1470,22 @@ namespace xmreg
// parse string representing given private key // parse string representing given private key
crypto::secret_key prv_view_key; crypto::secret_key prv_view_key;
if (!xmreg::parse_str_secret_key(viewkey_str, prv_view_key)) std::vector<crypto::secret_key> multiple_tx_secret_keys;
if (!xmreg::parse_str_secret_key(viewkey_str, multiple_tx_secret_keys))
{ {
cerr << "Cant parse the private key: " << viewkey_str << endl; cerr << "Cant parse the private key: " << viewkey_str << endl;
return string("Cant parse private key: " + viewkey_str); return string("Cant parse private key: " + viewkey_str);
} }
if (multiple_tx_secret_keys.size() == 1)
{
prv_view_key = multiple_tx_secret_keys[0];
}
else if (!tx_prove)
{
cerr << "Concatenated secret keys are only for tx proving!" << endl;
return string("Concatenated secret keys are only for tx proving!");
}
// just to see how would having spend keys could worked // just to see how would having spend keys could worked
@ -1648,12 +1660,20 @@ namespace xmreg
// public transaction key is combined with our viewkey // public transaction key is combined with our viewkey
// to create, so called, derived key. // to create, so called, derived key.
key_derivation derivation; key_derivation derivation;
std::vector<key_derivation> additional_derivations(txd.additional_pks.size());
//cout << multiple_tx_secret_keys.size() << " " << txd.additional_pks.size() + 1 << '\n';
if (tx_prove && multiple_tx_secret_keys.size() != txd.additional_pks.size() + 1)
{
return string("This transaction includes additional tx pubkeys whose size doesn't match with the provided tx secret keys");
}
public_key pub_key = tx_prove ? address_info.address.m_view_public_key : txd.pk; public_key pub_key = tx_prove ? address_info.address.m_view_public_key : txd.pk;
//cout << "txd.pk: " << pod_to_hex(txd.pk) << endl; //cout << "txd.pk: " << pod_to_hex(txd.pk) << endl;
if (!generate_key_derivation(pub_key, prv_view_key, derivation)) if (!generate_key_derivation(pub_key, tx_prove ? multiple_tx_secret_keys[0] : prv_view_key, derivation))
{ {
cerr << "Cant get derived key for: " << "\n" cerr << "Cant get derived key for: " << "\n"
<< "pub_tx_key: " << pub_key << " and " << "pub_tx_key: " << pub_key << " and "
@ -1661,6 +1681,17 @@ namespace xmreg
return string("Cant get key_derivation"); return string("Cant get key_derivation");
} }
for (size_t i = 0; i < txd.additional_pks.size(); ++i)
{
if (!generate_key_derivation(tx_prove ? pub_key : txd.additional_pks[i], tx_prove ? multiple_tx_secret_keys[i + 1] : prv_view_key, additional_derivations[i]))
{
cerr << "Cant get derived key for: " << "\n"
<< "pub_tx_key: " << txd.additional_pks[i] << " and "
<< "prv_view_key" << prv_view_key << endl;
return string("Cant get key_derivation");
}
}
// decrypt encrypted payment id, as used in integreated addresses // decrypt encrypted payment id, as used in integreated addresses
crypto::hash8 decrypted_payment_id8 = txd.payment_id8; crypto::hash8 decrypted_payment_id8 = txd.payment_id8;
@ -1701,6 +1732,16 @@ namespace xmreg
// check if generated public key matches the current output's key // check if generated public key matches the current output's key
bool mine_output = (outp.first.key == tx_pubkey); bool mine_output = (outp.first.key == tx_pubkey);
bool with_additional = false;
if (!mine_output && txd.additional_pks.size() == txd.output_pub_keys.size())
{
derive_public_key(additional_derivations[output_idx],
output_idx,
address_info.address.m_spend_public_key,
tx_pubkey);
mine_output = (outp.first.key == tx_pubkey);
with_additional = true;
}
// if mine output has RingCT, i.e., tx version is 2 // if mine output has RingCT, i.e., tx version is 2
if (mine_output && tx.version == 2) if (mine_output && tx.version == 2)
@ -1716,8 +1757,7 @@ namespace xmreg
bool r; bool r;
r = decode_ringct(tx.rct_signatures, r = decode_ringct(tx.rct_signatures,
pub_key, with_additional ? additional_derivations[output_idx] : derivation,
prv_view_key,
output_idx, output_idx,
tx.rct_signatures.ecdhInfo[output_idx].mask, tx.rct_signatures.ecdhInfo[output_idx].mask,
rct_amount); rct_amount);
@ -1888,12 +1928,14 @@ namespace xmreg
public_key mixin_tx_pub_key public_key mixin_tx_pub_key
= xmreg::get_tx_pub_key_from_received_outs(mixin_tx); = xmreg::get_tx_pub_key_from_received_outs(mixin_tx);
std::vector<public_key> mixin_additional_tx_pub_keys = cryptonote::get_additional_tx_pub_keys_from_extra(mixin_tx);
string mixin_tx_pub_key_str = pod_to_hex(mixin_tx_pub_key); string mixin_tx_pub_key_str = pod_to_hex(mixin_tx_pub_key);
// public transaction key is combined with our viewkey // public transaction key is combined with our viewkey
// to create, so called, derived key. // to create, so called, derived key.
key_derivation derivation; key_derivation derivation;
std::vector<key_derivation> additional_derivations(mixin_additional_tx_pub_keys.size());
if (!generate_key_derivation(mixin_tx_pub_key, prv_view_key, derivation)) if (!generate_key_derivation(mixin_tx_pub_key, prv_view_key, derivation))
{ {
@ -1903,6 +1945,17 @@ namespace xmreg
continue; continue;
} }
for (size_t i = 0; i < mixin_additional_tx_pub_keys.size(); ++i)
{
if (!generate_key_derivation(mixin_additional_tx_pub_keys[i], prv_view_key, additional_derivations[i]))
{
cerr << "Cant get derived key for: " << "\n"
<< "pub_tx_key: " << mixin_additional_tx_pub_keys[i] << " and "
<< "prv_view_key" << prv_view_key << endl;
continue;
}
}
// <public_key , amount , out idx> // <public_key , amount , out idx>
vector<tuple<txout_to_key, uint64_t, uint64_t>> output_pub_keys; vector<tuple<txout_to_key, uint64_t, uint64_t>> output_pub_keys;
@ -1953,6 +2006,16 @@ namespace xmreg
// check if generated public key matches the current output's key // check if generated public key matches the current output's key
bool mine_output = (txout_k.key == tx_pubkey_generated); bool mine_output = (txout_k.key == tx_pubkey_generated);
bool with_additional = false;
if (!mine_output && mixin_additional_tx_pub_keys.size() == output_pub_keys.size())
{
derive_public_key(additional_derivations[output_idx_in_tx],
output_idx_in_tx,
address_info.address.m_spend_public_key,
tx_pubkey_generated);
mine_output = (txout_k.key == tx_pubkey_generated);
with_additional = true;
}
if (mine_output && mixin_tx.version == 2) if (mine_output && mixin_tx.version == 2)
@ -1967,8 +2030,7 @@ namespace xmreg
bool r; bool r;
r = decode_ringct(mixin_tx.rct_signatures, r = decode_ringct(mixin_tx.rct_signatures,
mixin_tx_pub_key, with_additional ? additional_derivations[output_idx_in_tx] : derivation,
prv_view_key,
output_idx_in_tx, output_idx_in_tx,
mixin_tx.rct_signatures.ecdhInfo[output_idx_in_tx].mask, mixin_tx.rct_signatures.ecdhInfo[output_idx_in_tx].mask,
rct_amount); rct_amount);
@ -3308,6 +3370,7 @@ namespace xmreg
} }
public_key tx_pub_key = xmreg::get_tx_pub_key_from_received_outs(tx); public_key tx_pub_key = xmreg::get_tx_pub_key_from_received_outs(tx);
std::vector<public_key> additional_tx_pub_keys = cryptonote::get_additional_tx_pub_keys_from_extra(tx);
// cointbase txs have amounts in plain sight. // cointbase txs have amounts in plain sight.
// so use amount from ringct, only for non-coinbase txs // so use amount from ringct, only for non-coinbase txs
@ -3320,6 +3383,12 @@ namespace xmreg
td.m_internal_output_index, td.m_internal_output_index,
tx.rct_signatures.ecdhInfo[td.m_internal_output_index].mask, tx.rct_signatures.ecdhInfo[td.m_internal_output_index].mask,
xmr_amount); xmr_amount);
r = r || decode_ringct(tx.rct_signatures,
additional_tx_pub_keys[td.m_internal_output_index],
prv_view_key,
td.m_internal_output_index,
tx.rct_signatures.ecdhInfo[td.m_internal_output_index].mask,
xmr_amount);
if (!r) if (!r)
{ {
@ -4627,6 +4696,7 @@ namespace xmreg
// public transaction key is combined with our viewkey // public transaction key is combined with our viewkey
// to create, so called, derived key. // to create, so called, derived key.
key_derivation derivation; key_derivation derivation;
std::vector<key_derivation> additional_derivations(txd.additional_pks.size());
public_key pub_key = tx_prove ? address_info.address.m_view_public_key : txd.pk; public_key pub_key = tx_prove ? address_info.address.m_view_public_key : txd.pk;
@ -4638,6 +4708,15 @@ namespace xmreg
j_response["message"] = "Cant calculate key_derivation"; j_response["message"] = "Cant calculate key_derivation";
return j_response; return j_response;
} }
for (size_t i = 0; i < txd.additional_pks.size(); ++i)
{
if (!generate_key_derivation(txd.additional_pks[i], prv_view_key, additional_derivations[i]))
{
j_response["status"] = "error";
j_response["message"] = "Cant calculate key_derivation";
return j_response;
}
}
uint64_t output_idx {0}; uint64_t output_idx {0};
@ -4661,6 +4740,16 @@ namespace xmreg
// check if generated public key matches the current output's key // check if generated public key matches the current output's key
bool mine_output = (outp.first.key == tx_pubkey); bool mine_output = (outp.first.key == tx_pubkey);
bool with_additional = false;
if (!mine_output && txd.additional_pks.size() == txd.output_pub_keys.size())
{
derive_public_key(additional_derivations[output_idx],
output_idx,
address_info.address.m_spend_public_key,
tx_pubkey);
mine_output = (outp.first.key == tx_pubkey);
with_additional = true;
}
// if mine output has RingCT, i.e., tx version is 2 // if mine output has RingCT, i.e., tx version is 2
if (mine_output && tx.version == 2) if (mine_output && tx.version == 2)
@ -4676,8 +4765,7 @@ namespace xmreg
bool r; bool r;
r = decode_ringct(tx.rct_signatures, r = decode_ringct(tx.rct_signatures,
pub_key, with_additional ? additional_derivations[output_idx] : derivation,
prv_view_key,
output_idx, output_idx,
tx.rct_signatures.ecdhInfo[output_idx].mask, tx.rct_signatures.ecdhInfo[output_idx].mask,
rct_amount); rct_amount);
@ -5081,6 +5169,16 @@ namespace xmreg
return false; return false;
} }
std::vector<key_derivation> additional_derivations(txd.additional_pks.size());
for (size_t i = 0; i < txd.additional_pks.size(); ++i)
{
if (!generate_key_derivation(txd.additional_pks[i], prv_view_key, additional_derivations[i]))
{
error_msg = "Cant calculate key_derivation";
return false;
}
}
uint64_t output_idx{0}; uint64_t output_idx{0};
std::vector<uint64_t> money_transfered(tx.vout.size(), 0); std::vector<uint64_t> money_transfered(tx.vout.size(), 0);
@ -5103,6 +5201,16 @@ namespace xmreg
// check if generated public key matches the current output's key // check if generated public key matches the current output's key
bool mine_output = (outp.first.key == tx_pubkey); bool mine_output = (outp.first.key == tx_pubkey);
bool with_additional = false;
if (!mine_output && txd.additional_pks.size() == txd.output_pub_keys.size())
{
derive_public_key(additional_derivations[output_idx],
output_idx,
address.m_spend_public_key,
tx_pubkey);
mine_output = (outp.first.key == tx_pubkey);
with_additional = true;
}
// if mine output has RingCT, i.e., tx version is 2 // if mine output has RingCT, i.e., tx version is 2
if (mine_output && tx.version == 2) if (mine_output && tx.version == 2)
@ -5120,8 +5228,7 @@ namespace xmreg
rct::key mask = tx.rct_signatures.ecdhInfo[output_idx].mask; rct::key mask = tx.rct_signatures.ecdhInfo[output_idx].mask;
r = decode_ringct(tx.rct_signatures, r = decode_ringct(tx.rct_signatures,
txd.pk, with_additional ? additional_derivations[output_idx] : derivation,
prv_view_key,
output_idx, output_idx,
mask, mask,
rct_amount); rct_amount);
@ -5747,6 +5854,7 @@ namespace xmreg
// due to previous bug with sining txs: // due to previous bug with sining txs:
// https://github.com/monero-project/monero/pull/1358/commits/7abfc5474c0f86e16c405f154570310468b635c2 // https://github.com/monero-project/monero/pull/1358/commits/7abfc5474c0f86e16c405f154570310468b635c2
txd.pk = xmreg::get_tx_pub_key_from_received_outs(tx); txd.pk = xmreg::get_tx_pub_key_from_received_outs(tx);
txd.additional_pks = cryptonote::get_additional_tx_pub_keys_from_extra(tx);
// sum xmr in inputs and ouputs in the given tx // sum xmr in inputs and ouputs in the given tx

View file

@ -903,19 +903,29 @@ namespace xmreg
unsigned int i, unsigned int i,
rct::key & mask, rct::key & mask,
uint64_t & amount) uint64_t & amount)
{
crypto::key_derivation derivation;
bool r = crypto::generate_key_derivation(pub, sec, derivation);
if (!r)
{
cerr <<"Failed to generate key derivation to decode rct output " << i << endl;
return false;
}
return decode_ringct(rv, derivation, i, mask, amount);
}
bool
decode_ringct(const rct::rctSig& rv,
const crypto::key_derivation &derivation,
unsigned int i,
rct::key & mask,
uint64_t & amount)
{ {
try try
{ {
crypto::key_derivation derivation;
bool r = crypto::generate_key_derivation(pub, sec, derivation);
if (!r)
{
cerr <<"Failed to generate key derivation to decode rct output " << i << endl;
return false;
}
crypto::secret_key scalar1; crypto::secret_key scalar1;
crypto::derivation_to_scalar(derivation, i, scalar1); crypto::derivation_to_scalar(derivation, i, scalar1);

View file

@ -72,6 +72,22 @@ namespace xmreg
bool bool
parse_str_secret_key(const string& key_str, T& secret_key); parse_str_secret_key(const string& key_str, T& secret_key);
template <typename T>
bool
parse_str_secret_key(const string& key_str, std::vector<T>& secret_keys)
{
const size_t num_keys = key_str.size() / 64;
if (num_keys * 64 != key_str.size())
return false;
secret_keys.resize(num_keys);
for (size_t i = 0; i < num_keys; ++i)
{
if (!parse_str_secret_key(key_str.substr(64*i, 64), secret_keys[i]))
return false;
}
return true;
}
bool bool
get_tx_pub_key_from_str_hash(Blockchain& core_storage, get_tx_pub_key_from_str_hash(Blockchain& core_storage,
@ -227,6 +243,13 @@ namespace xmreg
rct::key & mask, rct::key & mask,
uint64_t & amount); uint64_t & amount);
bool
decode_ringct(const rct::rctSig & rv,
const crypto::key_derivation &derivation,
unsigned int i,
rct::key & mask,
uint64_t & amount);
bool bool
url_decode(const std::string& in, std::string& out); url_decode(const std::string& in, std::string& out);