mirror of
https://github.com/monero-project/monero.git
synced 2025-07-31 03:58:45 -04:00
make multisig work with subaddresses
Thanks to kenshi84 for help getting this work
This commit is contained in:
parent
dffa0dceaf
commit
fa5697127f
8 changed files with 89 additions and 82 deletions
|
@ -80,6 +80,31 @@ static std::atomic<uint64_t> tx_hashes_cached_count(0);
|
|||
static std::atomic<uint64_t> block_hashes_calculated_count(0);
|
||||
static std::atomic<uint64_t> block_hashes_cached_count(0);
|
||||
|
||||
#define CHECK_AND_ASSERT_THROW_MES_L1(expr, message) {if(!(expr)) {MWARNING(message); throw std::runtime_error(message);}}
|
||||
|
||||
namespace cryptonote
|
||||
{
|
||||
static inline unsigned char *operator &(ec_point &point) {
|
||||
return &reinterpret_cast<unsigned char &>(point);
|
||||
}
|
||||
static inline const unsigned char *operator &(const ec_point &point) {
|
||||
return &reinterpret_cast<const unsigned char &>(point);
|
||||
}
|
||||
|
||||
// a copy of rct::addKeys, since we can't link to libringct to avoid circular dependencies
|
||||
static void add_public_key(crypto::public_key &AB, const crypto::public_key &A, const crypto::public_key &B) {
|
||||
ge_p3 B2, A2;
|
||||
CHECK_AND_ASSERT_THROW_MES_L1(ge_frombytes_vartime(&B2, &B) == 0, "ge_frombytes_vartime failed at "+boost::lexical_cast<std::string>(__LINE__));
|
||||
CHECK_AND_ASSERT_THROW_MES_L1(ge_frombytes_vartime(&A2, &A) == 0, "ge_frombytes_vartime failed at "+boost::lexical_cast<std::string>(__LINE__));
|
||||
ge_cached tmp2;
|
||||
ge_p3_to_cached(&tmp2, &B2);
|
||||
ge_p1p1 tmp3;
|
||||
ge_add(&tmp3, &A2, &tmp2);
|
||||
ge_p1p1_to_p3(&A2, &tmp3);
|
||||
ge_p3_tobytes(&AB, &A2);
|
||||
}
|
||||
}
|
||||
|
||||
namespace cryptonote
|
||||
{
|
||||
//---------------------------------------------------------------
|
||||
|
@ -182,6 +207,7 @@ namespace cryptonote
|
|||
crypto::derive_secret_key(recv_derivation, real_output_index, ack.m_spend_secret_key, scalar_step1); // computes Hs(a*R || idx) + b
|
||||
|
||||
// step 2: add Hs(a || index_major || index_minor)
|
||||
crypto::secret_key subaddr_sk;
|
||||
crypto::secret_key scalar_step2;
|
||||
if (received_index.is_zero())
|
||||
{
|
||||
|
@ -189,13 +215,32 @@ namespace cryptonote
|
|||
}
|
||||
else
|
||||
{
|
||||
crypto::secret_key m = get_subaddress_secret_key(ack.m_view_secret_key, received_index);
|
||||
sc_add((unsigned char*)&scalar_step2, (unsigned char*)&scalar_step1, (unsigned char*)&m);
|
||||
subaddr_sk = get_subaddress_secret_key(ack.m_view_secret_key, received_index);
|
||||
sc_add((unsigned char*)&scalar_step2, (unsigned char*)&scalar_step1, (unsigned char*)&subaddr_sk);
|
||||
}
|
||||
|
||||
in_ephemeral.sec = scalar_step2;
|
||||
crypto::secret_key_to_public_key(in_ephemeral.sec, in_ephemeral.pub);
|
||||
CHECK_AND_ASSERT_MES(in_ephemeral.pub == out_key, false, "key image helper precomp: given output pubkey doesn't match the derived one");
|
||||
|
||||
if (ack.m_multisig_keys.empty())
|
||||
{
|
||||
// when not in multisig, we know the full spend secret key, so the output pubkey can be obtained by scalarmultBase
|
||||
CHECK_AND_ASSERT_MES(crypto::secret_key_to_public_key(in_ephemeral.sec, in_ephemeral.pub), false, "Failed to derive public key");
|
||||
}
|
||||
else
|
||||
{
|
||||
// when in multisig, we only know the partial spend secret key. but we do know the full spend public key, so the output pubkey can be obtained by using the standard CN key derivation
|
||||
CHECK_AND_ASSERT_MES(crypto::derive_public_key(recv_derivation, real_output_index, ack.m_account_address.m_spend_public_key, in_ephemeral.pub), false, "Failed to derive public key");
|
||||
// and don't forget to add the contribution from the subaddress part
|
||||
if (!received_index.is_zero())
|
||||
{
|
||||
crypto::public_key subaddr_pk;
|
||||
CHECK_AND_ASSERT_MES(crypto::secret_key_to_public_key(subaddr_sk, subaddr_pk), false, "Failed to derive public key");
|
||||
add_public_key(in_ephemeral.pub, in_ephemeral.pub, subaddr_pk);
|
||||
}
|
||||
}
|
||||
|
||||
CHECK_AND_ASSERT_MES(in_ephemeral.pub == out_key,
|
||||
false, "key image helper precomp: given output pubkey doesn't match the derived one");
|
||||
}
|
||||
|
||||
crypto::generate_key_image(in_ephemeral.pub, in_ephemeral.sec, ki);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue