Skip to content

Commit

Permalink
Merge pull request #227 from VanGrx/develop
Browse files Browse the repository at this point in the history
Develop
  • Loading branch information
VanGrx authored Jun 1, 2020
2 parents 5ecd3a6 + 8675064 commit 89b1700
Show file tree
Hide file tree
Showing 16 changed files with 267 additions and 77 deletions.
16 changes: 12 additions & 4 deletions src/blockchain_db/blockchain_db.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -253,11 +253,19 @@ uint64_t BlockchainDB::add_block( const block& blk
add_transaction(blk_hash, blk.miner_tx);
int tx_i = 0;
crypto::hash tx_hash = crypto::null_hash;
for (const transaction& tx : txs)
try
{
tx_hash = blk.tx_hashes[tx_i];
add_transaction(blk_hash, tx, &tx_hash);
++tx_i;
for (const transaction& tx : txs)
{
tx_hash = blk.tx_hashes[tx_i];
add_transaction(blk_hash, tx, &tx_hash);
++tx_i;
}
}
catch(SAFEX_TX_CONFLICT& e)
{
block_txn_abort();
throw e;
}
TIME_MEASURE_FINISH(time1);
time_add_transaction += time1;
Expand Down
3 changes: 2 additions & 1 deletion src/blockchain_db/blockchain_db.h
Original file line number Diff line number Diff line change
Expand Up @@ -172,8 +172,9 @@ namespace cryptonote
uint8_t relayed;
uint8_t do_not_relay;
uint8_t double_spend_seen: 1;
uint8_t safex_failed;

uint8_t padding[76]; // till 192 bytes
uint8_t padding[75]; // till 192 bytes
};

#define DBF_SAFE 1
Expand Down
4 changes: 2 additions & 2 deletions src/blockchain_db/lmdb/db_lmdb.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1250,7 +1250,7 @@ uint64_t BlockchainLMDB::add_advanced_output(const tx_out& tx_output, const uint
okadv.height = blockchain_height;
okadv.unlock_time = unlock_time;
okadv.output_id = output_id;
okadv.pubkey = txout.keys[0]; //todo if there are multiple keys, rest will go to data
okadv.pubkey = txout.key; //todo if there are multiple keys, rest will go to data
okadv.data = blobdata(txout.data.begin(),txout.data.end()); //no need to serialize vector to blob. Just copy it.

MDB_val_copy<cryptonote::output_advanced_data_t> adv_value(okadv);
Expand Down Expand Up @@ -3489,7 +3489,7 @@ bool BlockchainLMDB::for_all_advanced_outputs(std::function<bool(const crypto::h

txout_to_script txout = AUTO_VAL_INIT(txout);
txout.output_type = static_cast<uint8_t>(output.output_type);
txout.keys.push_back(output.pubkey); //todo handle case where there are multiple keys, and some are in data
txout.key = output.pubkey;

parse_and_validate_byte_array_from_blob(output.data, txout.data);

Expand Down
2 changes: 1 addition & 1 deletion src/checkpoints/checkpoints.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -165,7 +165,7 @@ namespace cryptonote
if (nettype == TESTNET)
{
ADD_CHECKPOINT(1, "753e1454ebc44ffb18d7b390f7393a66ce7f3a8aaaf1e4e857af9df4e80d5784");
ADD_CHECKPOINT(100000,"e255e1515acb9cccca8ebe9ce57718726c27c6e647878e6a18879dd42bb28434");
ADD_CHECKPOINT(100000,"94b27cd801da1cbbe886e5ac8e98d3147a555923050a526f0d4754ef31416d54");

return true;
}
Expand Down
14 changes: 8 additions & 6 deletions src/cryptonote_basic/cryptonote_basic.h
Original file line number Diff line number Diff line change
Expand Up @@ -63,14 +63,14 @@ namespace cryptonote

struct txout_to_script
{
std::vector<crypto::public_key> keys;
crypto::public_key key;
std::vector<uint8_t> data; //Local output data and state
uint8_t output_type{0};


BEGIN_SERIALIZE_OBJECT()
VARINT_FIELD(output_type)
FIELD(keys)
FIELD(key)
FIELD(data)
END_SERIALIZE()
};
Expand Down Expand Up @@ -115,7 +115,7 @@ namespace cryptonote

boost::optional<const crypto::public_key &> operator()(const cryptonote::txout_to_script &txout) const
{
return txout.keys[0];
return txout.key;
}
};

Expand Down Expand Up @@ -670,7 +670,8 @@ namespace cryptonote
bool token_seen = false;
bool advanced_seen = false;
for(auto it: vout){
switch(get_tx_out_type(it.target)){
auto curr_tx_out_type = get_tx_out_type(it.target);
switch(curr_tx_out_type){
case tx_out_type::out_cash:
if(!token_seen && !advanced_seen)
tx_type = tx_out_type::out_cash;
Expand All @@ -682,8 +683,9 @@ namespace cryptonote
}
break;
default:
if(get_tx_out_type(it.target) >= tx_out_type::out_advanced && get_tx_out_type(it.target) < tx_out_type::out_invalid
&& (tx_type < get_tx_out_type(it.target) || tx_type == tx_out_type::out_invalid)){
if(curr_tx_out_type >= tx_out_type::out_advanced && curr_tx_out_type < tx_out_type::out_invalid
&& ((tx_type < curr_tx_out_type && tx_type != tx_out_type::out_safex_purchase) || curr_tx_out_type == tx_out_type::out_safex_purchase
|| tx_type == tx_out_type::out_invalid)){
tx_type = get_tx_out_type(it.target);
advanced_seen = true;
}
Expand Down
2 changes: 1 addition & 1 deletion src/cryptonote_basic/cryptonote_boost_serialization.h
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,7 @@ namespace boost
inline void serialize(Archive &a, cryptonote::txout_to_script &x, const boost::serialization::version_type ver)
{
a & x.output_type;
a & x.keys;
a & x.key;
a & x.data;
}

Expand Down
15 changes: 11 additions & 4 deletions src/cryptonote_basic/cryptonote_format_utils.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -680,10 +680,17 @@ namespace cryptonote
{
for(const auto& in: tx.vin)
{
CHECK_AND_ASSERT_MES((in.type() == typeid(txin_to_script)) || (in.type() == typeid(txin_to_key))
|| (in.type() == typeid(txin_token_migration)) || (in.type() == typeid(txin_token_to_key)),
false, "wrong variant type: " << in.type().name() << ", expected " << typeid(txin_to_key).name() << ", in transaction id=" << get_transaction_hash(tx));

if (tx.version == 1) {
CHECK_AND_ASSERT_MES((in.type() == typeid(txin_to_key))
|| (in.type() == typeid(txin_token_migration)) || (in.type() == typeid(txin_token_to_key)),
false, "wrong variant type: " << in.type().name() << ", expected " << typeid(txin_to_key).name() << ", in transaction id=" << get_transaction_hash(tx));
} else if (tx.version == 2) {
CHECK_AND_ASSERT_MES((in.type() == typeid(txin_to_script)) || (in.type() == typeid(txin_to_key))
|| (in.type() == typeid(txin_token_migration)) || (in.type() == typeid(txin_token_to_key)),
false, "wrong variant type: " << in.type().name() << ", expected " << typeid(txin_to_key).name()
<< " or " << typeid(txin_token_to_key).name() << " or " << typeid(txin_token_migration).name()
<< " or " << typeid(txin_to_script).name() << ", in transaction id=" << get_transaction_hash(tx));
}
}
return true;
}
Expand Down
98 changes: 84 additions & 14 deletions src/cryptonote_core/blockchain.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -351,7 +351,6 @@ bool Blockchain::scan_outputkeys_for_indexes<Blockchain::outputs_generic_visitor
output_type = tx_out_type::out_safex_offer;
break;
case safex::command_t::simple_purchase:
//TODO: Check and set correct value
output_type = tx_out_type::out_cash;
break;
case safex::command_t::create_feedback:
Expand All @@ -372,6 +371,11 @@ bool Blockchain::scan_outputkeys_for_indexes<Blockchain::outputs_generic_visitor
if (!txin.key_offsets.size())
return false;

if(!safex::is_safex_key_image_verification_needed(txin.command_type) && txin.key_offsets.size() != 1){
MERROR_VER("Commands that don't have key image verification must have only 1 key offset");
return false;
}


std::vector<uint64_t> absolute_offsets;
uint64_t value_amount = 0;
Expand Down Expand Up @@ -3020,7 +3024,7 @@ bool Blockchain::check_safex_tx(const transaction &tx, tx_verification_context &
if (tx.version == 1) return true;

std::vector<txin_to_script> input_commands_to_execute;
std::set<safex::command_t> input_commands_to_check;
safex::command_t input_command_to_check;

bool only_donate_seen = true;
bool only_stake_seen = true;
Expand All @@ -3038,7 +3042,7 @@ bool Blockchain::check_safex_tx(const transaction &tx, tx_verification_context &
only_stake_seen = false;

input_commands_to_execute.push_back(txin_script);
input_commands_to_check.insert(txin_script.command_type);
input_command_to_check = txin_script.command_type;
}
}

Expand All @@ -3051,6 +3055,38 @@ bool Blockchain::check_safex_tx(const transaction &tx, tx_verification_context &
return false;
}


std::vector<tx_out_type> advanced_outputs;
bool network_fee_out = false;
bool purchase_out = false;
bool feedback_token_out = false;

for (auto txout: tx.vout)
{
if ((txout.target.type() == typeid(txout_to_script)))
{
auto txout_type = get_tx_out_type(txout.target);
advanced_outputs.push_back(txout_type);
if(txout_type == cryptonote::tx_out_type::out_safex_purchase)
purchase_out = true;
if(txout_type == cryptonote::tx_out_type::out_safex_feedback_token)
feedback_token_out = true;
if(txout_type == cryptonote::tx_out_type::out_network_fee)
network_fee_out = true;
}
}

// Per TX there can be :
// * 1 advanced output for all types
// * 3 outputs if tx is safex_purchase
// * 0 outputs if tx is token_unstake
if (!(advanced_outputs.size() == 1
|| (advanced_outputs.size() == 3 && network_fee_out && purchase_out && feedback_token_out)
|| (advanced_outputs.size() == 0 && input_command_to_check== safex::command_t::token_unstake))) {
tvc.m_safex_invalid_command = true;
return false;
}

//validate all command logic
for (const txin_to_script cmd: input_commands_to_execute)
if (!safex::validate_safex_command(*m_db, cmd)) {
Expand All @@ -3059,12 +3095,9 @@ bool Blockchain::check_safex_tx(const transaction &tx, tx_verification_context &
}

//check all commands tx restrictions
for (const safex::command_t cmd_type: input_commands_to_check){
if (!check_safex_tx_command(tx, cmd_type)){
tvc.m_safex_invalid_input = true;
return false;
}

if (!check_safex_tx_command(tx, input_command_to_check)){
tvc.m_safex_invalid_input = true;
return false;
}

return true;
Expand Down Expand Up @@ -3167,7 +3200,7 @@ bool Blockchain::check_safex_tx_command(const transaction &tx, const safex::comm
}

/* Check if donated cash amount matches */
if (outputs_donated_cash_amount >= input_cash_amount)
if (outputs_donated_cash_amount >= input_cash_amount || outputs_donated_cash_amount == 0)
{
MERROR("Invalid safex cash input amount");
return false;
Expand Down Expand Up @@ -3249,6 +3282,11 @@ bool Blockchain::check_safex_tx_command(const transaction &tx, const safex::comm

}

if(!create_account_seen){
MERROR("Create account output not found");
return false;
}

if(total_locked_tokens < SAFEX_CREATE_ACCOUNT_TOKEN_LOCK_FEE){
MERROR("Not enough tokens given as output. Needed: " + std::to_string(SAFEX_CREATE_ACCOUNT_TOKEN_LOCK_FEE) + ", actual sent: "+std::to_string(total_locked_tokens) );
return false;
Expand Down Expand Up @@ -3318,6 +3356,11 @@ bool Blockchain::check_safex_tx_command(const transaction &tx, const safex::comm
}
}
}

if(!edit_account_seen){
MERROR("Edit account output not found");
return false;
}
}
else if (command_type == safex::command_t::create_offer)
{
Expand Down Expand Up @@ -3384,6 +3427,11 @@ bool Blockchain::check_safex_tx_command(const transaction &tx, const safex::comm
}
}
}

if(!create_offer_seen){
MERROR("Create offer output not found");
return false;
}
}
else if (command_type == safex::command_t::edit_offer)
{
Expand Down Expand Up @@ -3448,6 +3496,10 @@ bool Blockchain::check_safex_tx_command(const transaction &tx, const safex::comm
}
}
}
if(!edit_offer_seen){
MERROR("Edit offer output not found");
return false;
}
}
else if (command_type == safex::command_t::simple_purchase)
{
Expand Down Expand Up @@ -3580,6 +3632,10 @@ bool Blockchain::check_safex_tx_command(const transaction &tx, const safex::comm
}
}
}
if(!feedback_seen){
MERROR("Create feedback output not found");
return false;
}
}
else if (command_type == safex::command_t::create_price_peg)
{
Expand Down Expand Up @@ -3652,6 +3708,10 @@ bool Blockchain::check_safex_tx_command(const transaction &tx, const safex::comm
}
}
}
if(!create_price_peg_seen){
MERROR("Create price peg output not found");
return false;
}
}
else if (command_type == safex::command_t::update_price_peg)
{
Expand Down Expand Up @@ -3693,6 +3753,10 @@ bool Blockchain::check_safex_tx_command(const transaction &tx, const safex::comm

}
}
if(!update_price_peg_seen){
MERROR("Update price peg output not found");
return false;
}
}
else
{
Expand Down Expand Up @@ -4233,6 +4297,12 @@ bool Blockchain::check_tx_inputs(transaction& tx, tx_verification_context &tvc,
return false;
}

if(!check_safex_tx(tx,tvc)){
tvc.m_verifivation_failed = true;
tvc.m_safex_verification_failed = true;
return false;
}

return true;
}

Expand Down Expand Up @@ -5094,13 +5164,12 @@ bool Blockchain::handle_block_to_main_chain(const block& bl, const crypto::hash&
}
catch (const SAFEX_TX_CONFLICT& e){

m_db->revert_transaction(bl.miner_tx.hash);
for(auto tx: txs){
cryptonote::transaction tmp;
if(m_db->get_tx(tx.hash,tmp))
m_db->revert_transaction(tx.hash);
}
auto it = find_if(txs.begin(),txs.end(),[e](transaction& tx){ return tx.hash == e.tx_hash; });
txs.erase(it);
LOG_ERROR("Error adding block with hash: " << id << " to blockchain, what = " << e.what());
bvc.m_verifivation_failed = true;
return_tx_to_pool(txs);
Expand All @@ -5109,6 +5178,7 @@ bool Blockchain::handle_block_to_main_chain(const block& bl, const crypto::hash&
catch (const std::exception& e)
{

m_db->revert_transaction(bl.miner_tx.hash);
for(auto tx: txs){
cryptonote::transaction tmp;
if(m_db->get_tx(tx.hash,tmp))
Expand Down Expand Up @@ -6557,7 +6627,7 @@ bool Blockchain::are_safex_tokens_unlocked(const std::vector<txin_v> &tx_vin) {
{
const txin_token_to_key &in = boost::get<txin_token_to_key>(txin);
if(in.token_amount != SAFEX_CREATE_ACCOUNT_TOKEN_LOCK_FEE)
return true;
continue;
const std::vector<uint64_t> absolute = cryptonote::relative_output_offsets_to_absolute(in.key_offsets);

// Now we search the offsets and find their txs
Expand All @@ -6574,7 +6644,7 @@ bool Blockchain::are_safex_tokens_unlocked(const std::vector<txin_v> &tx_vin) {
{
const txin_to_script &in = boost::get<txin_to_script>(txin);
if(in.token_amount != SAFEX_CREATE_ACCOUNT_TOKEN_LOCK_FEE)
return true;
continue;
const std::vector<uint64_t> absolute = cryptonote::relative_output_offsets_to_absolute(in.key_offsets);

// Now we search the offsets and find their txs
Expand Down
Loading

0 comments on commit 89b1700

Please sign in to comment.