Skip to content

Commit

Permalink
Merge pull request #204 from VanGrx/develop
Browse files Browse the repository at this point in the history
Feedback initial version
  • Loading branch information
VanGrx authored Feb 3, 2020
2 parents aa06b37 + bfa2d45 commit 8dd17e0
Show file tree
Hide file tree
Showing 36 changed files with 1,416 additions and 54 deletions.
5 changes: 5 additions & 0 deletions src/blockchain_db/blockchain_db.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -320,6 +320,11 @@ void BlockchainDB::remove_transaction(const crypto::hash& tx_hash)
remove_transaction_data(tx_hash, tx);
}

void BlockchainDB::revert_transaction(const crypto::hash &tx_hash)
{
remove_transaction(tx_hash);
}

block BlockchainDB::get_block_from_height(const uint64_t& height) const
{
blobdata bd = get_block_blob_from_height(height);
Expand Down
30 changes: 30 additions & 0 deletions src/blockchain_db/blockchain_db.h
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@
#include <safex/safex_account.h>
#include <safex/safex_offer.h>
#include <safex/safex_purchase.h>
#include <safex/safex_feedback.h>
#include "common/command_line.h"
#include "crypto/hash.h"
#include "cryptonote_basic/blobdatatype.h"
Expand Down Expand Up @@ -1185,6 +1186,17 @@ namespace cryptonote
virtual uint64_t height() const = 0;


// helper function to remove transaction from blockchain
/**
* @brief helper function to remove transaction from the blockchain
*
* This function encapsulates aspects of removing a transaction.
*
* @param tx_hash the hash of the transaction to be removed
*/
void revert_transaction(const crypto::hash &tx_hash);


/**
* <!--
* TODO: Rewrite (if necessary) such that all calls to remove_* are
Expand Down Expand Up @@ -1800,6 +1812,24 @@ namespace cryptonote
*/
virtual bool get_safex_offers( std::vector<safex::safex_offer> &safex_offers) const = 0;

/**
* @brief fetch safex feedbacks for given offer id from the blockchain
*
* The subclass should return safex feedbacks data
*
* @return True if no error ocurred
*/
virtual bool get_safex_feedbacks( std::vector<safex::safex_feedback> &safex_feedbacks, const crypto::hash& offer_id) const = 0;

/**
* @brief fetch safex offer's stars from the blockchain
*
* The subclass should return safex offer stars received
*
* @return True if no error ocurred
*/
virtual bool get_offer_stars_given(const crypto::hash offer_id, uint64_t &stars_received) const = 0;

//
// Hard fork related storage
//
Expand Down
161 changes: 156 additions & 5 deletions src/blockchain_db/lmdb/db_lmdb.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -319,7 +319,7 @@ const char* const LMDB_NETWORK_FEE_SUM = "network_fee_sum";
const char* const LMDB_TOKEN_LOCK_EXPIRY = "token_lock_expiry";
const char* const LMDB_SAFEX_ACCOUNT = "safex_account";
const char* const LMDB_SAFEX_OFFER = "safex_offer";

const char* const LMDB_SAFEX_FEEDBACK = "safex_feedback";

const char* const LMDB_PROPERTIES = "properties";

Expand Down Expand Up @@ -1394,7 +1394,7 @@ void BlockchainLMDB::remove_tx_outputs(const uint64_t tx_id, const transaction&
safex::create_purchase_data purchase_output_data;
parse_and_validate_object_from_blob(blobdata1, purchase_output_data);
remove_safex_purchase(purchase_output_data.offer_id,purchase_output_data.quantity);
} else if(output_type == tx_out_type::out_network_fee){
} else if(output_type == tx_out_type::out_network_fee || output_type == tx_out_type::out_safex_feedback_token){
remove_last_advanced_output();
}
else {
Expand Down Expand Up @@ -1629,6 +1629,22 @@ void BlockchainLMDB::process_command_input(const cryptonote::txin_to_script &txi
safex::safex_purchase sfx_purchase{result->quantity, result->price, result->offer_id, result->shipping};
create_safex_purchase(sfx_purchase);

}
else if (txin.command_type == safex::command_t::create_feedback)
{

std::unique_ptr<safex::command> cmd = safex::safex_command_serializer::parse_safex_object(txin.script, txin.command_type);
std::unique_ptr<safex::create_feedback_result> result(dynamic_cast<safex::create_feedback_result*>(cmd->execute(*this, txin)));
if (result->status != safex::execution_status::ok)
{
LOG_ERROR("Execution of safex purchase command failed, status:" << static_cast<int>(result->status));
throw1(DB_ERROR("Error executing safex purchase command"));
}

std::string comment{result->comment.begin(),result->comment.end()};
safex::safex_feedback sfx_feedback{result->stars_given, comment, result->offer_id};
create_safex_feedback(sfx_feedback);

}
else {
throw1(DB_ERROR("Unknown safex command type"));
Expand Down Expand Up @@ -1824,6 +1840,7 @@ void BlockchainLMDB::open(const std::string& filename, const int db_flags)
lmdb_db_open(txn, LMDB_TOKEN_LOCK_EXPIRY, MDB_INTEGERKEY | MDB_CREATE | MDB_DUPSORT | MDB_DUPFIXED, m_token_lock_expiry, "Failed to open db handle for m_token_lock_expiry");
lmdb_db_open(txn, LMDB_SAFEX_ACCOUNT, MDB_CREATE, m_safex_account, "Failed to open db handle for m_safex_account");
lmdb_db_open(txn, LMDB_SAFEX_OFFER, MDB_CREATE, m_safex_offer, "Failed to open db handle for m_safex_offer");
lmdb_db_open(txn, LMDB_SAFEX_FEEDBACK, MDB_CREATE, m_safex_feedback, "Failed to open db handle for m_safex_offer");


lmdb_db_open(txn, LMDB_PROPERTIES, MDB_CREATE, m_properties, "Failed to open db handle for m_properties");
Expand All @@ -1843,7 +1860,7 @@ void BlockchainLMDB::open(const std::string& filename, const int db_flags)
mdb_set_compare(txn, m_txpool_blob, compare_hash32);
mdb_set_compare(txn, m_safex_account, compare_hash32);
mdb_set_compare(txn, m_safex_offer, compare_hash32);

mdb_set_compare(txn, m_safex_feedback, compare_hash32);

mdb_set_compare(txn, m_properties, compare_string);

Expand Down Expand Up @@ -2011,6 +2028,8 @@ void BlockchainLMDB::reset()
throw0(DB_ERROR(lmdb_error("Failed to drop m_safex_account: ", result).c_str()));
if (auto result = mdb_drop(txn, m_safex_offer, 0))
throw0(DB_ERROR(lmdb_error("Failed to drop m_safex_offer: ", result).c_str()));
if (auto result = mdb_drop(txn, m_safex_feedback, 0))
throw0(DB_ERROR(lmdb_error("Failed to drop m_safex_feedback: ", result).c_str()));

if (auto result = mdb_drop(txn, m_properties, 0))
throw0(DB_ERROR(lmdb_error("Failed to drop m_properties: ", result).c_str()));
Expand Down Expand Up @@ -5177,6 +5196,9 @@ bool BlockchainLMDB::is_valid_transaction_output_type(const txout_target_v &txou
const cryptonote::blobdata accblob((uint8_t*)v.mv_data, (uint8_t*)v.mv_data+v.mv_size);
cryptonote::parse_and_validate_from_blob(accblob, sfx_offer);

if(sfx_offer.quantity - purchase.quantity > sfx_offer.quantity)
throw0(DB_ERROR("DB error attempting to create purchase: Not enough quantity of item"));

sfx_offer.quantity -= purchase.quantity;


Expand All @@ -5195,6 +5217,50 @@ bool BlockchainLMDB::is_valid_transaction_output_type(const txout_target_v &txou
}
}

void BlockchainLMDB::create_safex_feedback(const safex::safex_feedback& feedback) {
LOG_PRINT_L3("BlockchainLMDB::" << __func__);
check_open();
mdb_txn_cursors *m_cursors = &m_wcursors;
MDB_cursor *cur_safex_feedback;
CURSOR(safex_feedback)
cur_safex_feedback = m_cur_safex_feedback;


int result;
MDB_val_set(k, feedback.offer_id);
MDB_val v;

result = mdb_cursor_get(cur_safex_feedback, &k, &v, MDB_SET);
if (result == MDB_SUCCESS)
{
std::vector<safex::safex_feedback_db_data> sfx_feedbacks;
const cryptonote::blobdata feedbackblob((uint8_t*)v.mv_data, (uint8_t*)v.mv_data+v.mv_size);
cryptonote::parse_and_validate_from_blob(feedbackblob, sfx_feedbacks);

sfx_feedbacks.emplace_back(feedback.stars_given,feedback.comment);

MDB_val_copy<blobdata> vupdate(t_serializable_object_to_blob(sfx_feedbacks));
auto result2 = mdb_cursor_put(cur_safex_feedback, &k, &vupdate, (unsigned int) MDB_CURRENT);
if (result2 != MDB_SUCCESS)
throw0(DB_ERROR(lmdb_error("Failed to add feedback for offer id: "+boost::lexical_cast<std::string>(feedback.offer_id), result2).c_str()));
}
else if (result == MDB_NOTFOUND)
{
std::vector<safex::safex_feedback_db_data> sfx_feedbacks;
sfx_feedbacks.emplace_back(feedback.stars_given,feedback.comment);

MDB_val_copy<blobdata> vupdate(t_serializable_object_to_blob(sfx_feedbacks));

result = mdb_cursor_put(cur_safex_feedback, (MDB_val *)&k, &vupdate, MDB_NOOVERWRITE);
if (result)
throw0(DB_ERROR(lmdb_error("Failed to add offer data to db transaction: ", result).c_str()));
}
else
{
throw0(DB_ERROR(lmdb_error("DB error attempting to create feedback: ", result).c_str()));
}
}

bool BlockchainLMDB::get_account_key(const safex::account_username &username, crypto::public_key &pkey) const {

LOG_PRINT_L3("BlockchainLMDB::" << __func__);
Expand Down Expand Up @@ -5404,7 +5470,51 @@ bool BlockchainLMDB::is_valid_transaction_output_type(const txout_target_v &txou
return true;
}

bool BlockchainLMDB::get_account_data(const safex::account_username &username, std::vector<uint8_t> &data) const {
bool BlockchainLMDB::get_offer_stars_given(const crypto::hash offer_id, uint64_t &stars_received) const{
LOG_PRINT_L3("BlockchainLMDB::" << __func__);
check_open();

TXN_PREFIX_RDONLY();

MDB_cursor *cur_safex_feedback;
RCURSOR(safex_feedback)
cur_safex_feedback = m_cur_safex_feedback;


uint8_t temp[SAFEX_OFFER_DATA_MAX_SIZE*10];

MDB_val_set(k, offer_id);
MDB_val_set(v, temp);
auto get_result = mdb_cursor_get(cur_safex_feedback, &k, &v, MDB_SET);
if (get_result == MDB_NOTFOUND)
{
//throw0(DB_ERROR(lmdb_error(std::string("DB error account not found: ").append(username.c_str()), get_result).c_str()));
return false;
}
else if (get_result)
{
throw0(DB_ERROR(lmdb_error(std::string("DB error attempting to fetch offer with id: ").append(offer_id.data), get_result).c_str()));
}
else if (get_result == MDB_SUCCESS)
{
std::vector<safex::safex_feedback_db_data> feedbacks;
blobdata tmp{(char*)v.mv_data, v.mv_size};
parse_and_validate_object_from_blob<std::vector<safex::safex_feedback_db_data>>(tmp,feedbacks);

stars_received = 0;

for(auto it: feedbacks)
stars_received += it.stars_given;
stars_received /= feedbacks.size();
}

TXN_POSTFIX_RDONLY();

return true;
}


bool BlockchainLMDB::get_account_data(const safex::account_username &username, std::vector<uint8_t> &data) const {
LOG_PRINT_L3("BlockchainLMDB::" << __func__);
check_open();

Expand Down Expand Up @@ -5474,6 +5584,8 @@ bool BlockchainLMDB::is_valid_transaction_output_type(const txout_target_v &txou
std::string tmp{(char*)v.mv_data, v.mv_size};
parse_and_validate_object_from_blob<safex::create_offer_result>(tmp,offer_result);

offer.quantity = offer_result.quantity;

outputID = offer_result.output_ids.back();
}

Expand All @@ -5500,7 +5612,6 @@ bool BlockchainLMDB::is_valid_transaction_output_type(const txout_target_v &txou

offer.description = offer_result.description;
offer.seller = std::string{offer_result.seller.begin(),offer_result.seller.end()};
offer.quantity = offer_result.quantity;
offer.price = offer_result.price;
offer.offer_id = offer_result.offer_id;
offer.active = offer_result.active;
Expand Down Expand Up @@ -5679,6 +5790,46 @@ bool BlockchainLMDB::is_valid_transaction_output_type(const txout_target_v &txou
return true;
}

bool BlockchainLMDB::get_safex_feedbacks( std::vector<safex::safex_feedback> &safex_feedbacks, const crypto::hash& offer_id) const{
LOG_PRINT_L3("BlockchainLMDB::" << __func__);
check_open();

TXN_PREFIX_RDONLY();

MDB_cursor *cur_safex_feedback;
RCURSOR(safex_feedback)
cur_safex_feedback = m_cur_safex_feedback;


uint8_t temp[SAFEX_OFFER_DATA_MAX_SIZE*10];

MDB_val_set(k, offer_id);
MDB_val_set(v, temp);
auto get_result = mdb_cursor_get(cur_safex_feedback, &k, &v, MDB_SET);
if (get_result == MDB_NOTFOUND)
{
//throw0(DB_ERROR(lmdb_error(std::string("DB error account not found: ").append(username.c_str()), get_result).c_str()));
return false;
}
else if (get_result)
{
throw0(DB_ERROR(lmdb_error(std::string("DB error attempting to fetch offer with id: ").append(offer_id.data), get_result).c_str()));
}
else if (get_result == MDB_SUCCESS)
{
std::vector<safex::safex_feedback_db_data> feedbacks;
blobdata tmp{(char*)v.mv_data, v.mv_size};
parse_and_validate_object_from_blob<std::vector<safex::safex_feedback_db_data>>(tmp,feedbacks);

for(auto it: feedbacks) {
std::string comment{it.comment.begin(),it.comment.end()};
safex_feedbacks.emplace_back(it.stars_given, comment, offer_id);
}
}

TXN_POSTFIX_RDONLY();

return true; }



Expand Down
29 changes: 22 additions & 7 deletions src/blockchain_db/lmdb/db_lmdb.h
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@
#include <safex/safex_account.h>
#include <safex/safex_offer.h>
#include <safex/safex_purchase.h>
#include <safex/safex_feedback.h>
#include <safex/command.h>

#define ENABLE_AUTO_RESIZE
Expand Down Expand Up @@ -75,7 +76,7 @@ typedef struct mdb_txn_cursors
MDB_cursor *m_txc_token_lock_expiry;
MDB_cursor *m_txc_safex_account;
MDB_cursor *m_txc_safex_offer;

MDB_cursor *m_txc_safex_feedback;

} mdb_txn_cursors;

Expand All @@ -100,7 +101,7 @@ typedef struct mdb_txn_cursors
#define m_cur_token_lock_expiry m_cursors->m_txc_token_lock_expiry
#define m_cur_safex_account m_cursors->m_txc_safex_account
#define m_cur_safex_offer m_cursors->m_txc_safex_offer

#define m_cur_safex_feedback m_cursors->m_txc_safex_feedback

typedef struct mdb_rflags
{
Expand All @@ -126,6 +127,7 @@ typedef struct mdb_rflags
bool m_rf_token_lock_expiry;
bool m_rf_safex_account;
bool m_rf_safex_offer;
bool m_rf_safex_feedback;
} mdb_rflags;

typedef struct mdb_threadinfo
Expand Down Expand Up @@ -326,9 +328,12 @@ class BlockchainLMDB : public BlockchainDB
virtual bool get_safex_offers(std::vector<safex::safex_offer> &offers) const;
virtual bool get_create_account_output_id(const safex::account_username &username, uint64_t& output_id) const;
virtual bool get_create_offer_output_id(const crypto::hash& offer_id, uint64_t& output_id) const;
virtual bool get_offer_stars_given(const crypto::hash offer_id, uint64_t &stars_received) const;
virtual bool get_safex_feedbacks( std::vector<safex::safex_feedback> &safex_feedbacks, const crypto::hash& offer_id) const;



virtual uint64_t add_block( const block& blk
virtual uint64_t add_block( const block& blk
, const size_t& block_size
, const difficulty_type& cumulative_difficulty
, const uint64_t& coins_generated
Expand Down Expand Up @@ -539,12 +544,22 @@ class BlockchainLMDB : public BlockchainDB
/**
* Create purchase in database
*
* @param result safex purchase data
* @param purchase safex purchase data
*
* If any of this cannot be done, it throw the corresponding subclass of DB_EXCEPTION
*
*/
void create_safex_purchase(const safex::safex_purchase& result);
void create_safex_purchase(const safex::safex_purchase& purchase);

/**
* Create feedback in database
*
* @param feedback safex feedback data
*
* If any of this cannot be done, it throw the corresponding subclass of DB_EXCEPTION
*
*/
void create_safex_feedback(const safex::safex_feedback& feedback);
/**
* Remove advanced output from DB
*
Expand Down Expand Up @@ -651,10 +666,10 @@ class BlockchainLMDB : public BlockchainDB
MDB_dbi m_token_lock_expiry;
MDB_dbi m_safex_account;
MDB_dbi m_safex_offer;
MDB_dbi m_safex_feedback;



mutable uint64_t m_cum_size; // used in batch size estimation
mutable uint64_t m_cum_size; // used in batch size estimation
mutable unsigned int m_cum_count;
std::string m_folder;
mdb_txn_safe* m_write_txn; // may point to either a short-lived txn or a batch txn
Expand Down
Loading

0 comments on commit 8dd17e0

Please sign in to comment.