bool mark_spent_outputs(leveldb::WriteBatch& spend_batch, const output_point& previous_output, const input_point& spent_inpoint) { data_chunk spent_key = create_spent_key(previous_output), spend_value = create_spent_key(spent_inpoint); spend_batch.Put(slice(spent_key), slice(spend_value)); return true; }
bool bdb_common::mark_spent_outputs(txn_guard_ptr txn, const message::output_point& previous_output, const message::input_point& current_input) { readable_data_type spent_key, spend_value; spent_key.set(create_spent_key(previous_output)); spend_value.set(create_spent_key(current_input)); if (db_spends_->put(txn->get(), spent_key.get(), spend_value.get(), DB_NOOVERWRITE) != 0) return false; return true; }
bool leveldb_chain_keeper::remove_address(leveldb::WriteBatch& batch, const script& output_script, const output_point& outpoint) { payment_address address; if (!extract(address, output_script)) return false; data_chunk raw_address = create_address_key(address); BITCOIN_ASSERT(!raw_address.empty()); data_chunk outpoint_value = create_spent_key(outpoint); bool is_found = false; leveldb_iterator it(address_iterator(db_.addr, raw_address)); for (; valid_address_iterator(it, raw_address); it->Next()) { if (slice_to_output_point(it->value()) != outpoint) continue; // We found the address entry we were looking for. BITCOIN_ASSERT(!is_found); is_found = true; // Put changes into batch finally. batch.Delete(it->key()); break; } BITCOIN_ASSERT(it->status().ok()); if (!is_found) return false; return true; }
bool leveldb_chain_keeper::clear_transaction_data( leveldb_transaction_batch& batch, const transaction_type& remove_tx) { const hash_digest& tx_hash = hash_transaction(remove_tx); batch.tx.Delete(slice(tx_hash)); // Remove spends // ... spends don't exist for coinbase txs. if (!is_coinbase(remove_tx)) for (uint32_t input_index = 0; input_index < remove_tx.inputs.size(); ++input_index) { const transaction_input_type& input = remove_tx.inputs[input_index]; // We could check if the spend matches the inpoint for safety. //const input_point inpoint{tx_hash, input_index}; // Recreate the key... data_chunk spent_key = create_spent_key(input.previous_output); // ... Perform the delete. batch.spend.Delete(slice(spent_key)); } // Remove addresses for (uint32_t output_index = 0; output_index < remove_tx.outputs.size(); ++output_index) { const transaction_output_type& output = remove_tx.outputs[output_index]; if (!remove_address(batch.addr, output.output_script, {tx_hash, output_index})) return false; } return true; }
bool bdb_common::add_address(txn_guard_ptr txn, const script& output_script, const message::output_point& outpoint) { data_chunk raw_address = create_address_key(output_script); if (raw_address.empty()) return true; readable_data_type address_key, output_value; address_key.set(raw_address); output_value.set(create_spent_key(outpoint)); if (db_address_->put(txn->get(), address_key.get(), output_value.get(), 0) != 0) return false; return true; }
bool bdb_common::fetch_spend(txn_guard_ptr txn, const message::output_point& spent_output, message::input_point& input_spend) { readable_data_type search_spend; search_spend.set(create_spent_key(spent_output)); writable_data_type raw_spend; if (db_spends_->get(txn->get(), search_spend.get(), raw_spend.get(), 0) != 0) return false; const data_chunk raw_spend_data = raw_spend.data(); deserializer deserial(raw_spend_data); input_spend.hash = deserial.read_hash(); input_spend.index = deserial.read_4_bytes(); return true; }
bool leveldb_common::fetch_spend(const output_point& spent_output, input_point& input_spend) { data_chunk spent_key = create_spent_key(spent_output); std::string raw_spend; leveldb::Status status = db_.spend->Get( leveldb::ReadOptions(), slice(spent_key), &raw_spend); if (status.IsNotFound()) return false; else if (!status.ok()) { log_fatal(LOG_BLOCKCHAIN) << "fetch_spend: " << status.ToString(); return false; } const data_chunk raw_spend_data(raw_spend.begin(), raw_spend.end()); auto deserial = make_deserializer( raw_spend_data.begin(), raw_spend_data.end()); input_spend.hash = deserial.read_hash(); input_spend.index = deserial.read_4_bytes(); return true; }