mirror of https://github.com/oxen-io/oxen-core.git
Extend height tolerance to state_change tx "verifivation"
This commit is contained in:
parent
192ea32326
commit
3bc4f1ac13
|
@ -3215,9 +3215,11 @@ bool Blockchain::check_tx_inputs(transaction& tx, tx_verification_context &tvc,
|
|||
return false;
|
||||
}
|
||||
|
||||
if (!service_nodes::verify_tx_state_change(state_change, get_current_blockchain_height(), tvc.m_vote_ctx, *quorum, hf_version))
|
||||
if (!service_nodes::verify_tx_state_change(state_change, get_current_blockchain_height(), tvc, *quorum, hf_version))
|
||||
{
|
||||
tvc.m_verifivation_failed = true;
|
||||
// will be set by the above on serious failures (i.e. illegal value), but not for less
|
||||
// serious ones like state change heights slightly outside of allowed bounds:
|
||||
//tvc.m_verifivation_failed = true;
|
||||
MERROR_VER("tx " << get_transaction_hash(tx) << ": state change tx could not be completely verified reason: " << print_vote_verification_context(tvc.m_vote_ctx));
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -157,39 +157,50 @@ namespace service_nodes
|
|||
return true;
|
||||
}
|
||||
|
||||
// If we get an incoming vote of state change tx that is outside the acceptable range by this many
|
||||
// blocks then ignore it but don't trigger a connection drop; the sending side could be a couple
|
||||
// blocks out of sync and sending something that it thinks is legit.
|
||||
constexpr uint64_t VERIFY_HEIGHT_BUFFER = 5;
|
||||
|
||||
static bool bad_tx(cryptonote::tx_verification_context &tvc) {
|
||||
tvc.m_verifivation_failed = true;
|
||||
return false;
|
||||
}
|
||||
|
||||
bool verify_tx_state_change(const cryptonote::tx_extra_service_node_state_change &state_change,
|
||||
uint64_t latest_height,
|
||||
cryptonote::vote_verification_context &vvc,
|
||||
cryptonote::tx_verification_context &tvc,
|
||||
const service_nodes::testing_quorum &quorum,
|
||||
const uint8_t hf_version)
|
||||
{
|
||||
auto &vvc = tvc.m_vote_ctx;
|
||||
if (state_change.state != new_state::deregister && hf_version < cryptonote::network_version_12_checkpointing)
|
||||
{
|
||||
LOG_PRINT_L1("Non-deregister state changes are invalid before v12");
|
||||
return false;
|
||||
return bad_tx(tvc);
|
||||
}
|
||||
|
||||
if (state_change.state > new_state::recommission)
|
||||
{
|
||||
LOG_PRINT_L1("Unknown state change to new state: " << static_cast<uint16_t>(state_change.state));
|
||||
return false;
|
||||
return bad_tx(tvc);
|
||||
}
|
||||
|
||||
if (state_change.votes.size() < service_nodes::STATE_CHANGE_MIN_VOTES_TO_CHANGE_STATE)
|
||||
{
|
||||
LOG_PRINT_L1("Not enough votes");
|
||||
vvc.m_not_enough_votes = true;
|
||||
return false;
|
||||
return bad_tx(tvc);
|
||||
}
|
||||
|
||||
if (state_change.votes.size() > service_nodes::STATE_CHANGE_QUORUM_SIZE)
|
||||
{
|
||||
LOG_PRINT_L1("Too many votes");
|
||||
return false;
|
||||
return bad_tx(tvc);
|
||||
}
|
||||
|
||||
if (!bounds_check_worker_index(quorum, state_change.service_node_index, &vvc))
|
||||
return false;
|
||||
return bad_tx(tvc);
|
||||
|
||||
// Check if state_change is too old or too new to hold onto
|
||||
{
|
||||
|
@ -200,11 +211,12 @@ namespace service_nodes
|
|||
<< ", is newer than current height: " << latest_height
|
||||
<< " blocks and has been rejected.");
|
||||
vvc.m_invalid_block_height = true;
|
||||
if (state_change.block_height >= latest_height + VERIFY_HEIGHT_BUFFER)
|
||||
tvc.m_verifivation_failed = true;
|
||||
return false;
|
||||
}
|
||||
|
||||
uint64_t delta_height = latest_height - state_change.block_height;
|
||||
if (latest_height >= state_change.block_height && delta_height >= service_nodes::STATE_CHANGE_TX_LIFETIME_IN_BLOCKS)
|
||||
if (latest_height >= state_change.block_height + service_nodes::STATE_CHANGE_TX_LIFETIME_IN_BLOCKS)
|
||||
{
|
||||
LOG_PRINT_L1("Received state change tx for height: "
|
||||
<< state_change.block_height << " and service node: " << state_change.service_node_index
|
||||
|
@ -212,6 +224,8 @@ namespace service_nodes
|
|||
<< " (current height: " << latest_height << ") "
|
||||
<< "blocks and has been rejected.");
|
||||
vvc.m_invalid_block_height = true;
|
||||
if (latest_height >= state_change.block_height + (service_nodes::STATE_CHANGE_TX_LIFETIME_IN_BLOCKS + VERIFY_HEIGHT_BUFFER))
|
||||
tvc.m_verifivation_failed = true;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
@ -221,13 +235,13 @@ namespace service_nodes
|
|||
for (const auto &vote : state_change.votes)
|
||||
{
|
||||
if (!bounds_check_validator_index(quorum, vote.validator_index, &vvc))
|
||||
return false;
|
||||
return bad_tx(tvc);
|
||||
|
||||
if (++validator_set[vote.validator_index] > 1)
|
||||
{
|
||||
vvc.m_duplicate_voters = true;
|
||||
LOG_PRINT_L1("Voter quorum index is duplicated: " << vote.validator_index);
|
||||
return false;
|
||||
return bad_tx(tvc);
|
||||
}
|
||||
|
||||
crypto::public_key const &key = quorum.validators[vote.validator_index];
|
||||
|
@ -235,7 +249,7 @@ namespace service_nodes
|
|||
{
|
||||
LOG_PRINT_L1("Invalid signatures for votes");
|
||||
vvc.m_signature_not_valid = true;
|
||||
return false;
|
||||
return bad_tx(tvc);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -319,22 +333,17 @@ namespace service_nodes
|
|||
// NOTE: Validate vote age
|
||||
//
|
||||
{
|
||||
// If we get an incoming vote that is outside the acceptable range by this many votes then
|
||||
// just ignore it instead of dropping the connection; the sending side could be a couple
|
||||
// blocks out of sync and sending something that it thinks is legit.
|
||||
constexpr uint64_t VOTE_BUFFER = 5;
|
||||
|
||||
bool height_in_buffer = false;
|
||||
if (latest_height > vote.block_height + VOTE_LIFETIME)
|
||||
if (latest_height > vote.block_height + VERIFY_HEIGHT_BUFFER)
|
||||
{
|
||||
height_in_buffer = latest_height <= vote.block_height + (VOTE_LIFETIME + VOTE_BUFFER);
|
||||
LOG_PRINT_L1("Received vote for height: " << vote.block_height << ", is older than: " << VOTE_LIFETIME
|
||||
height_in_buffer = latest_height <= vote.block_height + (VOTE_LIFETIME + VERIFY_HEIGHT_BUFFER);
|
||||
LOG_PRINT_L1("Received vote for height: " << vote.block_height << ", is older than: " << VERIFY_HEIGHT_BUFFER
|
||||
<< " blocks and has been rejected.");
|
||||
vvc.m_invalid_block_height = true;
|
||||
}
|
||||
else if (vote.block_height > latest_height)
|
||||
{
|
||||
height_in_buffer = vote.block_height <= latest_height + VOTE_BUFFER;
|
||||
height_in_buffer = vote.block_height <= latest_height + VERIFY_HEIGHT_BUFFER;
|
||||
LOG_PRINT_L1("Received vote for height: " << vote.block_height << ", is newer than: " << latest_height
|
||||
<< " (latest block height) and has been rejected.");
|
||||
vvc.m_invalid_block_height = true;
|
||||
|
|
|
@ -42,6 +42,7 @@
|
|||
|
||||
namespace cryptonote
|
||||
{
|
||||
struct tx_verification_context;
|
||||
struct vote_verification_context;
|
||||
struct checkpoint_t;
|
||||
};
|
||||
|
@ -101,7 +102,7 @@ namespace service_nodes
|
|||
quorum_vote_t make_state_change_vote(uint64_t block_height, uint16_t index_in_group, uint16_t worker_index, new_state state, crypto::public_key const &pub_key, crypto::secret_key const &secret_key);
|
||||
|
||||
bool verify_checkpoint (cryptonote::checkpoint_t const &checkpoint, service_nodes::testing_quorum const &quorum);
|
||||
bool verify_tx_state_change (const cryptonote::tx_extra_service_node_state_change& state_change, uint64_t latest_height, cryptonote::vote_verification_context& vvc, const service_nodes::testing_quorum &quorum, uint8_t hf_version);
|
||||
bool verify_tx_state_change (const cryptonote::tx_extra_service_node_state_change& state_change, uint64_t latest_height, cryptonote::tx_verification_context& vvc, const service_nodes::testing_quorum &quorum, uint8_t hf_version);
|
||||
bool verify_vote (const quorum_vote_t& vote, uint64_t latest_height, cryptonote::vote_verification_context &vvc, const service_nodes::testing_quorum &quorum);
|
||||
crypto::signature make_signature_from_vote (quorum_vote_t const &vote, const crypto::public_key& pub, const crypto::secret_key& sec);
|
||||
crypto::signature make_signature_from_tx_state_change(cryptonote::tx_extra_service_node_state_change const &state_change, crypto::public_key const &pub, crypto::secret_key const &sec);
|
||||
|
|
Loading…
Reference in New Issue