void BlockchainDB::remove_transaction(const crypto::hash& tx_hash) { transaction tx = get_tx(tx_hash); for (const txin_v& tx_input : tx.vin) { if (tx_input.type() == typeid(txin_to_key)) { remove_spent_key(boost::get<txin_to_key>(tx_input).k_image); } } // need tx as tx.vout has the tx outputs, and the output amounts are needed remove_transaction_data(tx_hash, tx); }
void BlockchainDB::add_transaction(const crypto::hash& blk_hash, const transaction& tx, const crypto::hash* tx_hash_ptr) { crypto::hash tx_hash; if (!tx_hash_ptr) { // should only need to compute hash for miner transactions tx_hash = get_transaction_hash(tx); LOG_PRINT_L3("null tx_hash_ptr - needed to compute: " << tx_hash); } else { tx_hash = *tx_hash_ptr; } for (const txin_v& tx_input : tx.vin) { if (tx_input.type() == typeid(txin_to_key)) { add_spent_key(boost::get<txin_to_key>(tx_input).k_image); } else if (tx_input.type() == typeid(txin_gen)) { /* nothing to do here */ } else { LOG_PRINT_L1("Unsupported input type, removing key images and aborting transaction addition"); for (const txin_v& tx_input : tx.vin) { if (tx_input.type() == typeid(txin_to_key)) { remove_spent_key(boost::get<txin_to_key>(tx_input).k_image); } } return; } } add_transaction_data(blk_hash, tx, tx_hash); // iterate tx.vout using indices instead of C++11 foreach syntax because // we need the index for (uint64_t i = 0; i < tx.vout.size(); ++i) { add_output(tx_hash, tx.vout[i], i, tx.unlock_time); } }
void BlockchainDB::add_transaction(const crypto::hash& blk_hash, const transaction& tx, const crypto::hash* tx_hash_ptr, const crypto::hash* tx_prunable_hash_ptr) { bool miner_tx = false; crypto::hash tx_hash, tx_prunable_hash; if (!tx_hash_ptr) { // should only need to compute hash for miner transactions tx_hash = get_transaction_hash(tx); LOG_PRINT_L3("null tx_hash_ptr - needed to compute: " << tx_hash); } else { tx_hash = *tx_hash_ptr; } if (tx.version >= 2) { if (!tx_prunable_hash_ptr) tx_prunable_hash = get_transaction_prunable_hash(tx); else tx_prunable_hash = *tx_prunable_hash_ptr; } for (const txin_v& tx_input : tx.vin) { if (tx_input.type() == typeid(txin_to_key)) { add_spent_key(boost::get<txin_to_key>(tx_input).k_image); } else if (tx_input.type() == typeid(txin_gen)) { /* nothing to do here */ miner_tx = true; } else { LOG_PRINT_L1("Unsupported input type, removing key images and aborting transaction addition"); for (const txin_v& tx_input : tx.vin) { if (tx_input.type() == typeid(txin_to_key)) { remove_spent_key(boost::get<txin_to_key>(tx_input).k_image); } } return; } } uint64_t tx_id = add_transaction_data(blk_hash, tx, tx_hash, tx_prunable_hash); std::vector<uint64_t> amount_output_indices; // iterate tx.vout using indices instead of C++11 foreach syntax because // we need the index for (uint64_t i = 0; i < tx.vout.size(); ++i) { // miner v2 txes have their coinbase output in one single out to save space, // and we store them as rct outputs with an identity mask if (miner_tx && tx.version == 2) { cryptonote::tx_out vout = tx.vout[i]; rct::key commitment = rct::zeroCommit(vout.amount); vout.amount = 0; amount_output_indices.push_back(add_output(tx_hash, vout, i, tx.unlock_time, &commitment)); } else { amount_output_indices.push_back(add_output(tx_hash, tx.vout[i], i, tx.unlock_time, tx.version > 1 ? &tx.rct_signatures.outPk[i].mask : NULL)); } } add_tx_amount_output_indices(tx_id, amount_output_indices); }