1
0
Fork 0
forked from lthn/blockchain

implemented basic suppoer of wrapping in wallet(service commands) + inital support in simplewallet

This commit is contained in:
cryptozoidberg 2021-06-24 00:57:38 +02:00
parent 777b8f2e6a
commit 13e59ffafb
No known key found for this signature in database
GPG key ID: 22DEB97A54C6FDEC
5 changed files with 129 additions and 16 deletions

View file

@ -386,8 +386,14 @@ namespace currency
};
// applicable flags for tx_service_attachment::flags, can be combined using bitwise OR
#define TX_SERVICE_ATTACHMENT_ENCRYPT_BODY static_cast<uint8_t>(1 << 0)
#define TX_SERVICE_ATTACHMENT_DEFLATE_BODY static_cast<uint8_t>(1 << 1)
#define TX_SERVICE_ATTACHMENT_ENCRYPT_BODY static_cast<uint8_t>(1 << 0)
#define TX_SERVICE_ATTACHMENT_DEFLATE_BODY static_cast<uint8_t>(1 << 1)
// with this flag enabled body encrypted/decrypted with the key created as a derivation from onetime key and "spend keys" of receiver
#define TX_SERVICE_ATTACHMENT_ENCRYPT_BODY_ISOLATE_AUDITABLE static_cast<uint8_t>(1 << 2)
// add proof of content, without revealing secrete
#define TX_SERVICE_ATTACHMENT_ENCRYPT_ADD_PROOF static_cast<uint8_t>(1 << 3)
//,

View file

@ -759,8 +759,12 @@ namespace currency
struct encrypt_attach_visitor : public boost::static_visitor<void>
{
bool& m_was_crypted_entries;
const keypair& m_onetime_keypair;
const account_public_address& m_destination_addr;
const crypto::key_derivation& m_key;
encrypt_attach_visitor(bool& was_crypted_entries, const crypto::key_derivation& key) :m_was_crypted_entries(was_crypted_entries), m_key(key)
encrypt_attach_visitor(bool& was_crypted_entries, const crypto::key_derivation& key, const keypair& onetime_keypair = keypair(), const account_public_address& destination_addr = account_public_address()) :
m_was_crypted_entries(was_crypted_entries), m_key(key), m_onetime_keypair(onetime_keypair), m_destination_addr(m_destination_addr)
{}
void operator()(tx_comment& comment)
{
@ -789,6 +793,7 @@ namespace currency
}
void operator()(tx_service_attachment& sa)
{
const std::string orignal_body = sa.body;
if (sa.flags&TX_SERVICE_ATTACHMENT_DEFLATE_BODY)
{
zlib_helper::pack(sa.body);
@ -796,7 +801,27 @@ namespace currency
if (sa.flags&TX_SERVICE_ATTACHMENT_ENCRYPT_BODY)
{
crypto::chacha_crypt(sa.body, m_key);
crypto::key_derivation derivation_local = m_key;
if (sa.flags&TX_SERVICE_ATTACHMENT_ENCRYPT_BODY_ISOLATE_AUDITABLE)
{
CHECK_AND_ASSERT_THROW_MES(m_destination_addr.spend_public_key != currency::null_pkey && m_onetime_keypair.sec != currency::null_skey, "tx_service_attachment with TX_SERVICE_ATTACHMENT_ENCRYPT_BODY_ISOLATE_AUDITABLE: keys uninitialized");
//encrypt with "spend keys" only, to prevent auditable watchers decrypt it
bool r = crypto::generate_key_derivation(m_destination_addr.spend_public_key, m_onetime_keypair.sec, derivation_local);
crypto::chacha_crypt(sa.body, derivation_local);
}
else
{
crypto::chacha_crypt(sa.body, derivation_local);
}
if (sa.flags&TX_SERVICE_ATTACHMENT_ENCRYPT_ADD_PROOF)
{
//take hash from derivation and use it as a salt
crypto::hash derivation_hash = crypto::cn_fast_hash(&derivation_local, sizeof(derivation_local));
std::string salted_body = orignal_body;
string_tools::apped_pod_to_strbuff(salted_body, derivation_hash);
crypto::hash proof_hash = crypto::cn_fast_hash(salted_body.data(), salted_body.size());
sa.security.push_back(*(crypto::public_key*)&proof_hash);
}
m_was_crypted_entries = true;
}
}
@ -808,12 +833,18 @@ namespace currency
struct decrypt_attach_visitor : public boost::static_visitor<void>
{
const account_keys& m_acc_keys;
const crypto::public_key& m_tx_onetime_pubkey;
const crypto::key_derivation& rkey;
std::vector<payload_items_v>& rdecrypted_att;
decrypt_attach_visitor(const crypto::key_derivation& key,
std::vector<payload_items_v>& decrypted_att) :
std::vector<payload_items_v>& decrypted_att,
const account_keys& acc_keys = account_keys(),
const crypto::public_key& tx_onetime_pubkey = crypto::public_key()) :
rkey(key),
rdecrypted_att(decrypted_att)
rdecrypted_att(decrypted_att),
m_acc_keys(acc_keys),
m_tx_onetime_pubkey(tx_onetime_pubkey)
{}
void operator()(const tx_comment& comment)
{
@ -825,15 +856,44 @@ namespace currency
void operator()(const tx_service_attachment& sa)
{
tx_service_attachment local_sa = sa;
crypto::key_derivation derivation_local = rkey;
if (sa.flags&TX_SERVICE_ATTACHMENT_ENCRYPT_BODY)
{
crypto::chacha_crypt(local_sa.body, rkey);
if (sa.flags&TX_SERVICE_ATTACHMENT_ENCRYPT_BODY_ISOLATE_AUDITABLE)
{
if (m_acc_keys.spend_secret_key == null_skey)
{
//this watch only wallet, decrypting supposed to be impossible
return;
}
CHECK_AND_ASSERT_THROW_MES(m_acc_keys.spend_secret_key != currency::null_skey, "tx_service_attachment with TX_SERVICE_ATTACHMENT_ENCRYPT_BODY_ISOLATE_AUDITABLE: keys uninitialized");
bool r = crypto::generate_key_derivation(m_tx_onetime_pubkey, m_acc_keys.spend_secret_key, derivation_local);
CHECK_AND_ASSERT_THROW_MES(r, "Failed to generate_key_derivation at TX_SERVICE_ATTACHMENT_ENCRYPT_BODY_ISOLATE_AUDITABLE");
crypto::chacha_crypt(sa.body, derivation_local);
}
else
{
crypto::chacha_crypt(local_sa.body, derivation_local);
}
}
if (sa.flags&TX_SERVICE_ATTACHMENT_DEFLATE_BODY)
{
zlib_helper::unpack(local_sa.body);
}
if (sa.flags&TX_SERVICE_ATTACHMENT_ENCRYPT_BODY && sa.flags&TX_SERVICE_ATTACHMENT_ENCRYPT_ADD_PROOF)
{
CHECK_AND_ASSERT_MES(sa.security.size() == 1, void(), "Unexpected key in tx_service_attachment with TX_SERVICE_ATTACHMENT_ENCRYPT_BODY_ISOLATE_AUDITABLE");
//take hash from derivation and use it as a salt
crypto::hash derivation_hash = crypto::cn_fast_hash(&derivation_local, sizeof(derivation_local));
std::string salted_body = local_sa.body;
string_tools::apped_pod_to_strbuff(salted_body, derivation_hash);
crypto::hash proof_hash = crypto::cn_fast_hash(salted_body.data(), salted_body.size());
CHECK_AND_ASSERT_MES(*(crypto::public_key*)&proof_hash == sa.security.front(), void(), "Proof hash missmatch on decrypting with TX_SERVICE_ATTACHMENT_ENCRYPT_ADD_PROOF");
}
rdecrypted_att.push_back(local_sa);
}
@ -870,9 +930,10 @@ namespace currency
//---------------------------------------------------------------
template<class items_container_t>
bool decrypt_payload_items(const crypto::key_derivation& derivation, const items_container_t& items_to_decrypt, std::vector<payload_items_v>& decrypted_att)
bool decrypt_payload_items(const crypto::key_derivation& derivation, const items_container_t& items_to_decrypt, std::vector<payload_items_v>& decrypted_att, const account_keys& acc_keys = account_keys(),
const crypto::public_key& tx_onetime_pubkey = crypto::public_key())
{
decrypt_attach_visitor v(derivation, decrypted_att);
decrypt_attach_visitor v(derivation, decrypted_att, acc_keys, tx_onetime_pubkey);
for (auto& a : items_to_decrypt)
boost::apply_visitor(v, a);
@ -955,8 +1016,8 @@ namespace currency
return true;
}
decrypt_payload_items(derivation, tx.extra, decrypted_items);
decrypt_payload_items(derivation, tx.attachment, decrypted_items);
decrypt_payload_items(derivation, tx.extra, decrypted_items, acc_keys, get_tx_pub_key_from_extra(tx));
decrypt_payload_items(derivation, tx.attachment, decrypted_items, acc_keys, get_tx_pub_key_from_extra(tx));
return true;
}
@ -969,11 +1030,11 @@ namespace currency
bool was_attachment_crypted_entries = false;
bool was_extra_crypted_entries = false;
encrypt_attach_visitor v(was_attachment_crypted_entries, derivation);
encrypt_attach_visitor v(was_attachment_crypted_entries, derivation, tx_random_key, destination_addr);
for (auto& a : tx.attachment)
boost::apply_visitor(v, a);
encrypt_attach_visitor v2(was_extra_crypted_entries, derivation);
encrypt_attach_visitor v2(was_extra_crypted_entries, derivation, tx_random_key, destination_addr);
for (auto& a : tx.extra)
boost::apply_visitor(v2, a);
@ -2888,6 +2949,13 @@ namespace currency
return tools::base58::encode_addr(CURRENCY_PUBLIC_ADDRESS_BASE58_PREFIX, t_serializable_object_to_blob(addr)); // new format Zano address (normal)
}
//-----------------------------------------------------------------------
bool is_address_looks_like_wrapped(const std::string& addr)
{
if (addr.length() == 42 && addr.substr(0, 2) == "0x")
return true;
else return false;
}
//-----------------------------------------------------------------------
std::string get_account_address_and_payment_id_as_str(const account_public_address& addr, const payment_id_t& payment_id)
{
if (addr.flags == 0)

View file

@ -289,6 +289,7 @@ namespace currency
bool decrypt_payload_items(bool is_income, const transaction& tx, const account_keys& acc_keys, std::vector<payload_items_v>& decrypted_items);
void encrypt_attachments(transaction& tx, const account_keys& sender_keys, const account_public_address& destination_addr, const keypair& tx_random_key);
bool is_derivation_used_to_encrypt(const transaction& tx, const crypto::key_derivation& derivation);
bool is_address_looks_like_wrapped(const std::string& addr);
void load_wallet_transfer_info_flags(tools::wallet_public::wallet_transfer_info& x);
uint64_t get_tx_type(const transaction& tx);
uint64_t get_tx_type_ex(const transaction& tx, tx_out& htlc_out, txin_htlc& htlc_in);

View file

@ -20,6 +20,7 @@
#include "wallet/wallet_rpc_server.h"
#include "version.h"
#include "string_coding.h"
#include "wallet/wrap_service.h"
#include <cstdlib>
@ -1208,13 +1209,32 @@ bool simple_wallet::transfer(const std::vector<std::string> &args_)
return true;
}
std::vector<extra_v> extra;
vector<currency::tx_destination_entry> dsts;
bool wrapped_transaction = false;
for (size_t i = 0; i < local_args.size(); i += 2)
{
std::string integrated_payment_id;
currency::tx_destination_entry de;
de.addr.resize(1);
if(!(de.addr.size() == 1 && m_wallet->get_transfer_address(local_args[i], de.addr.front(), integrated_payment_id)))
//check if address looks like wrapped address
if (is_address_looks_like_wrapped(local_args[i]))
{
success_msg_writer(true) << "Address " << local_args[i] << " recognized as wrapped address, creating wrapping transaction...";
//put into service attachment specially encrypted entry which will contain wrap address and network
tx_service_attachment sa = AUTO_VAL_INIT(sa);
sa.service_id = BC_WRAP_SERVICE_ID;
sa.instruction = BC_WRAP_SERVICE_INSTRUCTION_ERC20;
sa.flags = TX_SERVICE_ATTACHMENT_ENCRYPT_BODY | TX_SERVICE_ATTACHMENT_ENCRYPT_BODY_ISOLATE_AUDITABLE;
sa.body = local_args[i];
extra.push_back(sa);
currency::account_public_address acc = AUTO_VAL_INIT(acc);
currency::get_account_address_from_str(acc, BC_WRAP_SERVICE_CUSTODY_WALLET);
de.addr.front() = acc;
wrapped_transaction = true;
//encrypt body with a special way
}else if(!(de.addr.size() == 1 && m_wallet->get_transfer_address(local_args[i], de.addr.front(), integrated_payment_id)))
{
fail_msg_writer() << "wrong address: " << local_args[i];
return true;
@ -1258,13 +1278,19 @@ bool simple_wallet::transfer(const std::vector<std::string> &args_)
try
{
currency::transaction tx;
std::vector<extra_v> extra;
m_wallet->transfer(dsts, fake_outs_count, 0, m_wallet->get_core_runtime_config().tx_default_fee, extra, attachments, tx);
if (!m_wallet->is_watch_only())
success_msg_writer(true) << "Money successfully sent, transaction " << get_transaction_hash(tx) << ", " << get_object_blobsize(tx) << " bytes";
{
if(wrapped_transaction)
success_msg_writer(true) << "Money successfully sent to wZano custody wallet, transaction " << get_transaction_hash(tx) << ", " << get_object_blobsize(tx) << " bytes";
else
success_msg_writer(true) << "Money successfully sent, transaction " << get_transaction_hash(tx) << ", " << get_object_blobsize(tx) << " bytes";
}
else
{
success_msg_writer(true) << "Transaction prepared for signing and saved into \"zano_tx_unsigned\" file, use full wallet to sign transfer and then use \"submit_transfer\" on this wallet to broadcast the transaction to the network";
}
}
catch (const tools::error::daemon_busy&)
{

12
src/wallet/wrap_service.h Normal file
View file

@ -0,0 +1,12 @@
// Copyright (c) 2014-2018 Zano Project
// Distributed under the MIT/X11 software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#pragma once
#define BC_WRAP_SERVICE_ID "W"
#define BC_WRAP_SERVICE_INSTRUCTION_ERC20 "ERC20" //erc20 wrapped operation
#define BC_WRAP_SERVICE_CUSTODY_WALLET "aZxbJPXzkjCJDpGEVvkMir9B4fRKPo73r2e5D7nLHuVgEBXXQYc2Tk2hHroxVwiCDLDHZu215pgNocUsrchH4HHzWbHzL4nMfPq"