forked from lthn/blockchain
Merge branch 'develop' of github.com:hyle-team/zano into develop
This commit is contained in:
commit
4d1acdd783
23 changed files with 1379 additions and 1347 deletions
|
|
@ -3910,14 +3910,14 @@ bool blockchain_storage::is_tx_spendtime_unlocked(uint64_t unlock_time) const
|
|||
}
|
||||
|
||||
//------------------------------------------------------------------
|
||||
bool blockchain_storage::check_tx_input(const transaction& tx, size_t in_index, const txin_to_key& txin, const crypto::hash& tx_prefix_hash, const std::vector<crypto::signature>& sig, uint64_t& max_related_block_height, uint64_t& max_unlock_time) const
|
||||
bool blockchain_storage::check_tx_input(const transaction& tx, size_t in_index, const txin_to_key& txin, const crypto::hash& tx_prefix_hash, const std::vector<crypto::signature>& sig, uint64_t& max_related_block_height, uint64_t& source_max_unlock_time_for_pos_coinbase) const
|
||||
{
|
||||
CRITICAL_REGION_LOCAL(m_read_lock);
|
||||
|
||||
//TIME_MEASURE_START_PD(tx_check_inputs_loop_ch_in_get_keys_loop);
|
||||
|
||||
std::vector<crypto::public_key> output_keys;
|
||||
if(!get_output_keys_for_input_with_checks(tx, txin, output_keys, max_related_block_height, max_unlock_time))
|
||||
if(!get_output_keys_for_input_with_checks(tx, txin, output_keys, max_related_block_height, source_max_unlock_time_for_pos_coinbase))
|
||||
{
|
||||
LOG_PRINT_L0("Failed to get output keys for input #" << in_index << " (amount = " << print_money(txin.amount) << ", key_offset.size = " << txin.key_offsets.size() << ")");
|
||||
return false;
|
||||
|
|
@ -3936,7 +3936,7 @@ bool blockchain_storage::check_tx_input(const transaction& tx, size_t in_index,
|
|||
// 1) source tx unlock time validity
|
||||
// 2) mixin restrictions
|
||||
// 3) general gindex/ref_by_id corectness
|
||||
bool blockchain_storage::get_output_keys_for_input_with_checks(const transaction& tx, const txin_to_key& txin, std::vector<crypto::public_key>& output_keys, uint64_t& max_related_block_height, uint64_t& max_unlock_time) const
|
||||
bool blockchain_storage::get_output_keys_for_input_with_checks(const transaction& tx, const txin_to_key& txin, std::vector<crypto::public_key>& output_keys, uint64_t& max_related_block_height, uint64_t& source_max_unlock_time_for_pos_coinbase) const
|
||||
{
|
||||
CRITICAL_REGION_LOCAL(m_read_lock);
|
||||
|
||||
|
|
@ -3944,10 +3944,13 @@ bool blockchain_storage::get_output_keys_for_input_with_checks(const transaction
|
|||
{
|
||||
std::vector<crypto::public_key >& m_results_collector;
|
||||
const blockchain_storage& m_bch;
|
||||
uint64_t& m_max_unlock_time;
|
||||
uint64_t& m_source_max_unlock_time_for_pos_coinbase;
|
||||
outputs_visitor(std::vector<crypto::public_key>& results_collector,
|
||||
const blockchain_storage& bch,
|
||||
uint64_t& max_unlock_time) :m_results_collector(results_collector), m_bch(bch), m_max_unlock_time(max_unlock_time)
|
||||
uint64_t& source_max_unlock_time_for_pos_coinbase)
|
||||
: m_results_collector(results_collector)
|
||||
, m_bch(bch)
|
||||
, m_source_max_unlock_time_for_pos_coinbase(source_max_unlock_time_for_pos_coinbase)
|
||||
{}
|
||||
bool handle_output(const transaction& source_tx, const transaction& validated_tx, const tx_out& out, uint64_t out_i)
|
||||
{
|
||||
|
|
@ -3956,8 +3959,9 @@ bool blockchain_storage::get_output_keys_for_input_with_checks(const transaction
|
|||
//let coinbase sources for PoS block to have locked inputs, the outputs supposed to be locked same way, except the reward
|
||||
if (is_coinbase(validated_tx) && is_pos_block(validated_tx))
|
||||
{
|
||||
if (source_out_unlock_time > m_max_unlock_time)
|
||||
m_max_unlock_time = source_out_unlock_time;
|
||||
CHECK_AND_ASSERT_MES(should_unlock_value_be_treated_as_block_height(source_out_unlock_time), false, "source output #" << out_i << " is locked by time, not by height, which is not allowed for PoS coinbase");
|
||||
if (source_out_unlock_time > m_source_max_unlock_time_for_pos_coinbase)
|
||||
m_source_max_unlock_time_for_pos_coinbase = source_out_unlock_time;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
@ -3968,7 +3972,6 @@ bool blockchain_storage::get_output_keys_for_input_with_checks(const transaction
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
if(out.target.type() != typeid(txout_to_key))
|
||||
{
|
||||
LOG_PRINT_L0("Output have wrong type id, which=" << out.target.which());
|
||||
|
|
@ -3980,7 +3983,7 @@ bool blockchain_storage::get_output_keys_for_input_with_checks(const transaction
|
|||
}
|
||||
};
|
||||
|
||||
outputs_visitor vi(output_keys, *this, max_unlock_time);
|
||||
outputs_visitor vi(output_keys, *this, source_max_unlock_time_for_pos_coinbase);
|
||||
return scan_outputkeys_for_indexes(tx, txin, vi, max_related_block_height);
|
||||
}
|
||||
//------------------------------------------------------------------
|
||||
|
|
@ -4438,13 +4441,13 @@ bool blockchain_storage::validate_tx_for_hardfork_specific_terms(const transacti
|
|||
return true;
|
||||
}
|
||||
//------------------------------------------------------------------
|
||||
bool blockchain_storage::validate_pos_coinbase_outs_unlock_time(const transaction& miner_tx, uint64_t staked_amount, uint64_t max_unlock_time)const
|
||||
bool blockchain_storage::validate_pos_coinbase_outs_unlock_time(const transaction& miner_tx, uint64_t staked_amount, uint64_t source_max_unlock_time)const
|
||||
{
|
||||
uint64_t major_unlock_time = get_tx_x_detail<etc_tx_details_unlock_time>(miner_tx);
|
||||
if (major_unlock_time)
|
||||
{
|
||||
//if there was etc_tx_details_unlock_time present in tx, then ignore etc_tx_details_unlock_time2
|
||||
if (major_unlock_time < max_unlock_time)
|
||||
if (major_unlock_time < source_max_unlock_time)
|
||||
return false;
|
||||
else
|
||||
return true;
|
||||
|
|
@ -4458,11 +4461,13 @@ bool blockchain_storage::validate_pos_coinbase_outs_unlock_time(const transactio
|
|||
CHECK_AND_ASSERT_MES(ut2.unlock_time_array.size() == miner_tx.vout.size(), false, "ut2.unlock_time_array.size()<" << ut2.unlock_time_array.size()
|
||||
<< "> != miner_tx.vout.size()<" << miner_tx.vout.size() << ">");
|
||||
|
||||
uint64_t amount_of_coins_in_unlock_in_range = 0;
|
||||
uint64_t amount_of_coins_in_unlock_in_range = 0; // amount of outputs locked for at least the same time
|
||||
|
||||
for (uint64_t i = 0; i != miner_tx.vout.size(); i++)
|
||||
{
|
||||
if (ut2.unlock_time_array[i] >= max_unlock_time)
|
||||
uint64_t unlock_value = ut2.unlock_time_array[i];
|
||||
CHECK_AND_ASSERT_MES(should_unlock_value_be_treated_as_block_height(unlock_value), false, "output #" << i << " is locked by time, not buy height, which is not allowed for PoS coinbase");
|
||||
if (unlock_value >= source_max_unlock_time)
|
||||
amount_of_coins_in_unlock_in_range += miner_tx.vout[i].amount;
|
||||
}
|
||||
|
||||
|
|
@ -4549,22 +4554,22 @@ bool blockchain_storage::validate_pos_block(const block& b,
|
|||
{
|
||||
// Do coinstake input validation for main chain only.
|
||||
// Txs in alternative PoS blocks (including miner_tx) are validated by validate_alt_block_txs()
|
||||
uint64_t max_unlock_time = 0;
|
||||
r = check_tx_input(b.miner_tx, 1, coinstake_in, id, b.miner_tx.signatures[0], max_related_block_height, max_unlock_time);
|
||||
uint64_t source_max_unlock_time_for_pos_coinbase = 0;
|
||||
r = check_tx_input(b.miner_tx, 1, coinstake_in, id, b.miner_tx.signatures[0], max_related_block_height, source_max_unlock_time_for_pos_coinbase);
|
||||
CHECK_AND_ASSERT_MES(r, false, "Failed to validate coinstake input in miner tx, block_id = " << get_block_hash(b));
|
||||
|
||||
if (get_block_height(b) > m_core_runtime_config.hard_fork1_starts_after_height)
|
||||
{
|
||||
uint64_t last_pow_h = get_last_x_block_height(false);
|
||||
CHECK_AND_ASSERT_MES(max_related_block_height <= last_pow_h, false, "Failed to failed to validate coinbase in pos block, condition failed: max_related_block_height(" << max_related_block_height << ") < last_pow_h(" << last_pow_h << ")");
|
||||
CHECK_AND_ASSERT_MES(max_related_block_height <= last_pow_h, false, "Failed to validate coinbase in PoS block, condition failed: max_related_block_height(" << max_related_block_height << ") <= last_pow_h(" << last_pow_h << ")");
|
||||
//let's check that coinbase amount and unlock time
|
||||
r = validate_pos_coinbase_outs_unlock_time(b.miner_tx, coinstake_in.amount, max_unlock_time);
|
||||
r = validate_pos_coinbase_outs_unlock_time(b.miner_tx, coinstake_in.amount, source_max_unlock_time_for_pos_coinbase);
|
||||
CHECK_AND_ASSERT_MES(r, false, "Failed to validate_pos_coinbase_outs_unlock_time() in miner tx, block_id = " << get_block_hash(b)
|
||||
<< "max_unlock_time=" << max_unlock_time);
|
||||
<< "source_max_unlock_time_for_pos_coinbase=" << source_max_unlock_time_for_pos_coinbase);
|
||||
}
|
||||
else
|
||||
{
|
||||
CHECK_AND_ASSERT_MES(is_tx_spendtime_unlocked(max_unlock_time), false, "Failed to failed to validate coinbase in pos block, condition failed: is_tx_spendtime_unlocked(max_unlock_time)(" << max_unlock_time << ")");
|
||||
CHECK_AND_ASSERT_MES(is_tx_spendtime_unlocked(source_max_unlock_time_for_pos_coinbase), false, "Failed to validate coinbase in PoS block, condition failed: is_tx_spendtime_unlocked(source_max_unlock_time_for_pos_coinbase)(" << source_max_unlock_time_for_pos_coinbase << ")");
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -267,14 +267,14 @@ namespace currency
|
|||
uint64_t get_aliases_count()const;
|
||||
uint64_t get_block_h_older_then(uint64_t timestamp) const;
|
||||
bool validate_tx_service_attachmens_in_services(const tx_service_attachment& a, size_t i, const transaction& tx)const;
|
||||
bool check_tx_input(const transaction& tx, size_t in_index, const txin_to_key& txin, const crypto::hash& tx_prefix_hash, const std::vector<crypto::signature>& sig, uint64_t& max_related_block_height, uint64_t& max_unlock_time)const;
|
||||
bool check_tx_input(const transaction& tx, size_t in_index, const txin_to_key& txin, const crypto::hash& tx_prefix_hash, const std::vector<crypto::signature>& sig, uint64_t& max_related_block_height, uint64_t& source_max_unlock_time_for_pos_coinbase)const;
|
||||
bool check_tx_input(const transaction& tx, size_t in_index, const txin_multisig& txin, const crypto::hash& tx_prefix_hash, const std::vector<crypto::signature>& sig, uint64_t& max_related_block_height)const;
|
||||
bool check_tx_inputs(const transaction& tx, const crypto::hash& tx_prefix_hash, uint64_t& max_used_block_height)const;
|
||||
bool check_tx_inputs(const transaction& tx, const crypto::hash& tx_prefix_hash) const;
|
||||
bool check_tx_inputs(const transaction& tx, const crypto::hash& tx_prefix_hash, uint64_t& max_used_block_height, crypto::hash& max_used_block_id)const;
|
||||
bool check_ms_input(const transaction& tx, size_t in_index, const txin_multisig& txin, const crypto::hash& tx_prefix_hash, const std::vector<crypto::signature>& sig, const transaction& source_tx, size_t out_n) const;
|
||||
bool validate_tx_for_hardfork_specific_terms(const transaction& tx, const crypto::hash& tx_id, uint64_t block_height) const;
|
||||
bool get_output_keys_for_input_with_checks(const transaction& tx, const txin_to_key& txin, std::vector<crypto::public_key>& output_keys, uint64_t& max_related_block_height, uint64_t& max_unlock_time) const;
|
||||
bool get_output_keys_for_input_with_checks(const transaction& tx, const txin_to_key& txin, std::vector<crypto::public_key>& output_keys, uint64_t& max_related_block_height, uint64_t& source_max_unlock_time_for_pos_coinbase) const;
|
||||
bool check_tokey_input(const transaction& tx, size_t in_index, const txin_to_key& txin, const crypto::hash& tx_prefix_hash, const std::vector<crypto::signature>& sig, const std::vector<const crypto::public_key*>& output_keys_ptrs) const;
|
||||
uint64_t get_current_comulative_blocksize_limit()const;
|
||||
uint64_t get_current_hashrate(size_t aprox_count)const;
|
||||
|
|
@ -312,7 +312,7 @@ namespace currency
|
|||
bool build_stake_modifier(stake_modifier_type& sm, const alt_chain_type& alt_chain = alt_chain_type(), uint64_t split_height = 0, crypto::hash *p_last_block_hash = nullptr) const;
|
||||
|
||||
bool scan_pos(const COMMAND_RPC_SCAN_POS::request& sp, COMMAND_RPC_SCAN_POS::response& rsp)const;
|
||||
bool validate_pos_coinbase_outs_unlock_time(const transaction& miner_tx, uint64_t staked_amount, uint64_t max_unlock_time)const;
|
||||
bool validate_pos_coinbase_outs_unlock_time(const transaction& miner_tx, uint64_t staked_amount, uint64_t source_max_unlock_time)const;
|
||||
bool validate_pos_block(const block& b, const crypto::hash& id, bool for_altchain)const;
|
||||
bool validate_pos_block(const block& b, wide_difficulty_type basic_diff, const crypto::hash& id, bool for_altchain)const;
|
||||
bool validate_pos_block(const block& b,
|
||||
|
|
|
|||
|
|
@ -88,7 +88,7 @@ namespace currency
|
|||
return 0;
|
||||
|
||||
CHECK_AND_ASSERT_THROW_MES(ut2.unlock_time_array.size() > o_i, "unlock_time_array.size=" << ut2.unlock_time_array.size()
|
||||
<< " is less then o_i=" << o_i << " in tx: " << get_transaction_hash(tx));
|
||||
<< " is less or equal to o_i=" << o_i << " in tx: " << get_transaction_hash(tx));
|
||||
|
||||
return ut2.unlock_time_array[o_i];
|
||||
}
|
||||
|
|
|
|||
|
|
@ -85,6 +85,7 @@ namespace currency
|
|||
uint64_t get_tx_unlock_time(const transaction& tx, uint64_t o_i);
|
||||
uint64_t get_tx_max_unlock_time(const transaction& tx);
|
||||
bool get_tx_max_min_unlock_time(const transaction& tx, uint64_t& max_unlock_time, uint64_t& min_unlock_time);
|
||||
inline bool should_unlock_value_be_treated_as_block_height(uint64_t v) { return v < CURRENCY_MAX_BLOCK_NUMBER; }
|
||||
inline uint64_t get_tx_flags(const transaction& tx) { return get_tx_x_detail<etc_tx_details_flags>(tx); }
|
||||
inline uint64_t get_tx_expiration_time(const transaction& tx) {return get_tx_x_detail<etc_tx_details_expiration_time>(tx); }
|
||||
inline void set_tx_unlock_time(transaction& tx, uint64_t v) { set_tx_x_detail<etc_tx_details_unlock_time>(tx, v); }
|
||||
|
|
@ -106,4 +107,4 @@ namespace currency
|
|||
size_t get_object_blobsize(const transaction& t, uint64_t prefix_blob_size);
|
||||
blobdata tx_to_blob(const transaction& b);
|
||||
bool tx_to_blob(const transaction& b, blobdata& b_blob);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -39,8 +39,10 @@
|
|||
"SYNCING": "Syncing wallet"
|
||||
},
|
||||
"CONTACTS": "Contacts",
|
||||
"CONTACTS_TOOLTIP": "Contacts option available only with Master Password enabled",
|
||||
"SETTINGS": "Settings",
|
||||
"LOG_OUT": "Log out",
|
||||
"LOG_OUT_TOOLTIP": "Logout option available only with Master Password enabled",
|
||||
"SYNCHRONIZATION": {
|
||||
"OFFLINE": "Offline",
|
||||
"ONLINE": "Online",
|
||||
|
|
@ -60,7 +62,9 @@
|
|||
"CRITICAL_TOOLTIP": "<span class=\"critical-update\">Critical update available.</span><i class=\"icon\"></i><span>Update strongly recommended!</span>",
|
||||
"TIME": "System time differs from network",
|
||||
"TIME_TOOLTIP": "<span class=\"wrong-time\">Wrong system time!</span><br><span>Check and repair your system time.</span>"
|
||||
}
|
||||
},
|
||||
"BLOCK": "Block",
|
||||
"OF": "of"
|
||||
},
|
||||
"MAIN": {
|
||||
"TITLE": "Create or open the wallet to start using Zano",
|
||||
|
|
|
|||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
|
|
@ -5800,8 +5800,8 @@ __webpack_require__.r(__webpack_exports__);
|
|||
/*! no static exports found */
|
||||
/***/ (function(module, exports, __webpack_require__) {
|
||||
|
||||
__webpack_require__(/*! c:\Projects\zano\src\gui\qt-daemon\html_source\src\polyfills.ts */"./src/polyfills.ts");
|
||||
module.exports = __webpack_require__(/*! c:\Projects\zano\src\gui\qt-daemon\html_source\node_modules\@angular-devkit\build-angular\src\angular-cli-files\models\jit-polyfills.js */"./node_modules/@angular-devkit/build-angular/src/angular-cli-files/models/jit-polyfills.js");
|
||||
__webpack_require__(/*! D:\Projects\Projects now\zano\src\gui\qt-daemon\html_source\src\polyfills.ts */"./src/polyfills.ts");
|
||||
module.exports = __webpack_require__(/*! D:\Projects\Projects now\zano\src\gui\qt-daemon\html_source\node_modules\@angular-devkit\build-angular\src\angular-cli-files\models\jit-polyfills.js */"./node_modules/@angular-devkit/build-angular/src/angular-cli-files/models/jit-polyfills.js");
|
||||
|
||||
|
||||
/***/ })
|
||||
|
|
|
|||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because it is too large
Load diff
File diff suppressed because one or more lines are too long
|
|
@ -22,6 +22,7 @@ export class VariablesService {
|
|||
public exp_med_ts = 0;
|
||||
public net_time_delta_median = 0;
|
||||
public height_app = 0;
|
||||
public height_max = 0;
|
||||
public last_build_available = '';
|
||||
public last_build_displaymode = 0;
|
||||
public daemon_state = 3;
|
||||
|
|
@ -59,18 +60,23 @@ export class VariablesService {
|
|||
|
||||
getExpMedTsEvent = new BehaviorSubject(null);
|
||||
getHeightAppEvent = new BehaviorSubject(null);
|
||||
getHeightMaxEvent = new BehaviorSubject(null);
|
||||
getRefreshStackingEvent = new BehaviorSubject(null);
|
||||
getAliasChangedEvent = new BehaviorSubject(null);
|
||||
|
||||
public idle = new Idle()
|
||||
.whenNotInteractive()
|
||||
.do(() => {
|
||||
this.ngZone.run(() => {
|
||||
if (this.appPass == '') {
|
||||
this.restartCountdown();
|
||||
} else {
|
||||
this.ngZone.run(() => {
|
||||
this.idle.stop();
|
||||
this.appPass = '';
|
||||
this.appLogin = false;
|
||||
this.router.navigate(['/login'], {queryParams: {type: 'auth'}});
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
public allContextMenu: ContextMenuComponent;
|
||||
|
|
@ -94,6 +100,13 @@ export class VariablesService {
|
|||
}
|
||||
}
|
||||
|
||||
setHeightMax(height: number) {
|
||||
if (height !== this.height_max) {
|
||||
this.height_max = height;
|
||||
this.getHeightMaxEvent.next(height);
|
||||
}
|
||||
}
|
||||
|
||||
setRefreshStacking(wallet_id: number) {
|
||||
this.getHeightAppEvent.next(wallet_id);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -172,6 +172,7 @@ export class AppComponent implements OnInit, OnDestroy {
|
|||
this.variablesService.last_build_available = data.last_build_available;
|
||||
this.variablesService.last_build_displaymode = data.last_build_displaymode;
|
||||
this.variablesService.setHeightApp(data.height);
|
||||
this.variablesService.setHeightMax(data.max_net_seen_height);
|
||||
|
||||
this.ngZone.run(() => {
|
||||
this.variablesService.daemon_state = data['daemon_network_state'];
|
||||
|
|
|
|||
|
|
@ -38,24 +38,40 @@
|
|||
</div>
|
||||
</div>
|
||||
<div class="sidebar-settings">
|
||||
<div class="wrap-button" routerLinkActive="active">
|
||||
<button (click)="contactsRoute()" [class.disabled]="variablesService.daemon_state !== 2" [disabled]="variablesService.daemon_state !== 2">
|
||||
<div class="wrap-button" routerLinkActive="active" *ngIf="variablesService.appPass === ''; else contactsShow" tooltip="{{ 'SIDEBAR.CONTACTS_TOOLTIP' | translate }}" placement="top" tooltipClass="table-tooltip account-tooltip" [delay]="500">
|
||||
<button (click)="contactsRoute()" [class.disabled]="variablesService.daemon_state !== 2 || variablesService.appPass === ''" [disabled]="variablesService.daemon_state !== 2 || variablesService.appPass === ''">
|
||||
<i class="icon contacts"></i>
|
||||
<span>{{ 'SIDEBAR.CONTACTS' | translate }}</span>
|
||||
</button>
|
||||
</div>
|
||||
<ng-template #contactsShow>
|
||||
<div class="wrap-button" routerLinkActive="active">
|
||||
<button (click)="contactsRoute()">
|
||||
<i class="icon contacts"></i>
|
||||
<span>{{ 'SIDEBAR.CONTACTS' | translate }}</span>
|
||||
</button>
|
||||
</div>
|
||||
</ng-template>
|
||||
<div class="wrap-button" routerLinkActive="active">
|
||||
<button [routerLink]="['/settings']">
|
||||
<i class="icon settings"></i>
|
||||
<span>{{ 'SIDEBAR.SETTINGS' | translate }}</span>
|
||||
</button>
|
||||
</div>
|
||||
<div class="wrap-button">
|
||||
<button (click)="logOut()">
|
||||
<div class="wrap-button" *ngIf="variablesService.appPass === ''; else masterPass" tooltip="{{ 'SIDEBAR.LOG_OUT_TOOLTIP' | translate }}" placement="bottom" tooltipClass="table-tooltip account-tooltip" [delay]="500">
|
||||
<button (click)="logOut()" [class.disabled]="variablesService.appPass === ''" [disabled]="variablesService.appPass === ''">
|
||||
<i class="icon logout"></i>
|
||||
<span>{{ 'SIDEBAR.LOG_OUT' | translate }}</span>
|
||||
</button>
|
||||
</div>
|
||||
<ng-template #masterPass>
|
||||
<div class="wrap-button">
|
||||
<button (click)="logOut()">
|
||||
<i class="icon logout"></i>
|
||||
<span>{{ 'SIDEBAR.LOG_OUT' | translate }}</span>
|
||||
</button>
|
||||
</div>
|
||||
</ng-template>
|
||||
</div>
|
||||
<div class="sidebar-synchronization-status">
|
||||
<div class="status-container">
|
||||
|
|
@ -87,6 +103,11 @@
|
|||
<div class="loading" *ngIf="variablesService.daemon_state === 3"></div>
|
||||
</div>
|
||||
</div>
|
||||
<ng-container *ngIf="variablesService.daemon_state === 1 || variablesService.daemon_state === 3">
|
||||
<ng-container *ngIf="variablesService.daemon_state === 1">
|
||||
<div class="progress-height">{{ 'SIDEBAR.BLOCK' | translate }} {{ variablesService.height_app }} {{ 'SIDEBAR.OF' | translate }} {{ variablesService.height_max }}</div>
|
||||
</ng-container>
|
||||
</ng-container>
|
||||
<div class="update-container" *ngIf="(variablesService.daemon_state === 0 || variablesService.daemon_state === 2) && [2, 3, 4].indexOf(variablesService.last_build_displaymode) !== -1">
|
||||
<ng-container *ngIf="variablesService.last_build_displaymode === 2">
|
||||
<div class="update-text standard">
|
||||
|
|
@ -118,3 +139,4 @@
|
|||
<i class="icon time" tooltip="{{ 'SIDEBAR.UPDATE.TIME_TOOLTIP' | translate }}" placement="right-bottom" tooltipClass="update-tooltip important" [delay]="500"></i>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
|
|
|||
|
|
@ -225,14 +225,17 @@
|
|||
|
||||
.sidebar-synchronization-status {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: flex-start;
|
||||
flex: 0 0 7rem;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
flex: 0 0 8rem;
|
||||
font-size: 1.3rem;
|
||||
|
||||
.progress-height {
|
||||
margin-top: 1rem;
|
||||
}
|
||||
|
||||
.status-container {
|
||||
position: relative;
|
||||
flex-grow: 1;
|
||||
text-align: left;
|
||||
|
||||
.offline, .online {
|
||||
|
|
@ -280,6 +283,9 @@
|
|||
line-height: 0.7rem;
|
||||
padding-left: 0.7rem;
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
.loading {
|
||||
|
|
|
|||
|
|
@ -39,8 +39,10 @@
|
|||
"SYNCING": "Syncing wallet"
|
||||
},
|
||||
"CONTACTS": "Contacts",
|
||||
"CONTACTS_TOOLTIP": "Contacts option available only with Master Password enabled",
|
||||
"SETTINGS": "Settings",
|
||||
"LOG_OUT": "Log out",
|
||||
"LOG_OUT_TOOLTIP": "Logout option available only with Master Password enabled",
|
||||
"SYNCHRONIZATION": {
|
||||
"OFFLINE": "Offline",
|
||||
"ONLINE": "Online",
|
||||
|
|
@ -60,7 +62,9 @@
|
|||
"CRITICAL_TOOLTIP": "<span class=\"critical-update\">Critical update available.</span><i class=\"icon\"></i><span>Update strongly recommended!</span>",
|
||||
"TIME": "System time differs from network",
|
||||
"TIME_TOOLTIP": "<span class=\"wrong-time\">Wrong system time!</span><br><span>Check and repair your system time.</span>"
|
||||
}
|
||||
},
|
||||
"BLOCK": "Block",
|
||||
"OF": "of"
|
||||
},
|
||||
"MAIN": {
|
||||
"TITLE": "Create or open the wallet to start using Zano",
|
||||
|
|
|
|||
|
|
@ -2,6 +2,6 @@
|
|||
|
||||
#define BUILD_COMMIT_ID "@VERSION@"
|
||||
#define PROJECT_VERSION "1.0"
|
||||
#define PROJECT_VERSION_BUILD_NO 53
|
||||
#define PROJECT_VERSION_BUILD_NO 54
|
||||
#define PROJECT_VERSION_BUILD_NO_STR STRINGIFY_EXPAND(PROJECT_VERSION_BUILD_NO)
|
||||
#define PROJECT_VERSION_LONG PROJECT_VERSION "." PROJECT_VERSION_BUILD_NO_STR "[" BUILD_COMMIT_ID "]"
|
||||
|
|
|
|||
|
|
@ -1124,13 +1124,13 @@ void append_vector_by_another_vector(U& dst, const V& src)
|
|||
|
||||
#define MAKE_TX_ATTACH(EVENTS, TX_VAR, FROM, TO, AMOUNT, HEAD, ATTACH) MAKE_TX_ATTACH_FEE(EVENTS, TX_VAR, FROM, TO, AMOUNT, TESTS_DEFAULT_FEE, HEAD, ATTACH)
|
||||
|
||||
#define MAKE_MINER_TX_AND_KEY_MANUALLY(TX, BLK, KEY) \
|
||||
transaction TX; \
|
||||
if (!construct_miner_tx_manually(get_block_height(BLK) + 1, generator.get_already_generated_coins(BLK), \
|
||||
miner_account.get_keys().m_account_address, TX, 0, KEY)) \
|
||||
#define MAKE_MINER_TX_AND_KEY_MANUALLY(TX, PREV_BLOCK, P_KEYPAIR) \
|
||||
transaction TX; \
|
||||
if (!construct_miner_tx_manually(get_block_height(PREV_BLOCK) + 1, generator.get_already_generated_coins(PREV_BLOCK), \
|
||||
miner_account.get_keys().m_account_address, TX, 0, P_KEYPAIR)) \
|
||||
return false;
|
||||
|
||||
#define MAKE_MINER_TX_MANUALLY(TX, BLK) MAKE_MINER_TX_AND_KEY_MANUALLY(TX, BLK, 0)
|
||||
#define MAKE_MINER_TX_MANUALLY(TX, PREV_BLOCK) MAKE_MINER_TX_AND_KEY_MANUALLY(TX, PREV_BLOCK, nullptr)
|
||||
|
||||
#define SET_EVENT_VISITOR_SETT(VEC_EVENTS, SETT, VAL) VEC_EVENTS.push_back(event_visitor_settings(SETT, VAL));
|
||||
|
||||
|
|
|
|||
|
|
@ -947,6 +947,7 @@ int main(int argc, char* argv[])
|
|||
GENERATE_AND_PLAY(hard_fork_1_unlock_time_2_in_coinbase);
|
||||
GENERATE_AND_PLAY(hard_fork_1_chain_switch_pow_only);
|
||||
GENERATE_AND_PLAY(hard_fork_1_checkpoint_basic_test);
|
||||
GENERATE_AND_PLAY(hard_fork_1_pos_locked_height_vs_time);
|
||||
//GENERATE_AND_PLAY(gen_block_reward); */
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -10,6 +10,20 @@
|
|||
|
||||
using namespace currency;
|
||||
|
||||
template<typename extra_t>
|
||||
void remove_unlock_v1_entries_from_extra(extra_t& extra)
|
||||
{
|
||||
extra.erase(std::remove_if(extra.begin(), extra.end(), [](extra_v& extra_element) { return extra_element.type() == typeid(etc_tx_details_unlock_time); }), extra.end());
|
||||
}
|
||||
|
||||
template<typename extra_t>
|
||||
void remove_unlock_v2_entries_from_extra(extra_t& extra)
|
||||
{
|
||||
extra.erase(std::remove_if(extra.begin(), extra.end(), [](extra_v& extra_element) { return extra_element.type() == typeid(etc_tx_details_unlock_time2); }), extra.end());
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
hard_fork_1_base_test::hard_fork_1_base_test(size_t hardfork_height)
|
||||
: m_hardfork_height(hardfork_height)
|
||||
{
|
||||
|
|
@ -28,7 +42,6 @@ bool hard_fork_1_base_test::configure_core(currency::core& c, size_t ev_index, c
|
|||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
|
||||
hard_fork_1_unlock_time_2_in_normal_tx::hard_fork_1_unlock_time_2_in_normal_tx()
|
||||
: hard_fork_1_base_test(12)
|
||||
{
|
||||
|
|
@ -341,9 +354,27 @@ bool hard_fork_1_checkpoint_basic_test::generate(std::vector<test_event_entry>&
|
|||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
struct unique_amount_params
|
||||
{
|
||||
unique_amount_params(uint64_t amount, uint64_t count) : amount(amount), count(count) {}
|
||||
uint64_t amount;
|
||||
uint64_t count;
|
||||
};
|
||||
|
||||
// check that the given amount has only one non-zero gidit
|
||||
// 3000 => true
|
||||
// 11000 => false
|
||||
bool does_amount_have_one_non_zero_digit(uint64_t amount)
|
||||
{
|
||||
size_t count = 0;
|
||||
auto f = [&count](uint64_t){ ++count; };
|
||||
decompose_amount_into_digits(amount, DEFAULT_DUST_THRESHOLD, f, f);
|
||||
return count == 1;
|
||||
}
|
||||
|
||||
|
||||
hard_fork_1_pos_and_locked_coins::hard_fork_1_pos_and_locked_coins()
|
||||
: hard_fork_1_base_test(13) // hardfork height
|
||||
, m_unique_amount(TESTS_DEFAULT_FEE * 9)
|
||||
: hard_fork_1_base_test(25) // hardfork height
|
||||
{
|
||||
REGISTER_CALLBACK_METHOD(hard_fork_1_pos_and_locked_coins, check_outputs_with_unique_amount);
|
||||
}
|
||||
|
|
@ -353,14 +384,24 @@ bool hard_fork_1_pos_and_locked_coins::generate(std::vector<test_event_entry>& e
|
|||
bool r = false;
|
||||
GENERATE_ACCOUNT(miner_acc);
|
||||
GENERATE_ACCOUNT(alice_acc);
|
||||
GENERATE_ACCOUNT(bob_acc);
|
||||
MAKE_GENESIS_BLOCK(events, blk_0, miner_acc, test_core_time::get_time());
|
||||
generator.set_hardfork_height(m_hardfork_height);
|
||||
DO_CALLBACK(events, "configure_core");
|
||||
REWIND_BLOCKS_N_WITH_TIME(events, blk_0r, blk_0, miner_acc, CURRENCY_MINED_MONEY_UNLOCK_WINDOW + 3);
|
||||
|
||||
DO_CALLBACK_PARAMS(events, "check_outputs_with_unique_amount", static_cast<size_t>(0));
|
||||
const uint64_t unique_amount_alice = TESTS_DEFAULT_FEE * 9;
|
||||
const uint64_t unique_amount_bob = TESTS_DEFAULT_FEE * 3;
|
||||
|
||||
CHECK_AND_ASSERT_MES(does_amount_have_one_non_zero_digit(unique_amount_alice), false, "does_amount_have_one_non_zero_digit failed for Alice");
|
||||
CHECK_AND_ASSERT_MES(does_amount_have_one_non_zero_digit(unique_amount_bob), false, "does_amount_have_one_non_zero_digit failed for Bob");
|
||||
|
||||
// make sure no outputs have such unique amounts
|
||||
DO_CALLBACK_PARAMS(events, "check_outputs_with_unique_amount", unique_amount_params(unique_amount_alice, 0) );
|
||||
DO_CALLBACK_PARAMS(events, "check_outputs_with_unique_amount", unique_amount_params(unique_amount_bob, 0) );
|
||||
|
||||
// create few locked outputs in the blockchain with unique amount
|
||||
// tx_0 : miner -> Alice
|
||||
std::vector<extra_v> extra;
|
||||
etc_tx_details_unlock_time ut = AUTO_VAL_INIT(ut);
|
||||
ut.v = 100; // locked until block 100
|
||||
|
|
@ -368,56 +409,317 @@ bool hard_fork_1_pos_and_locked_coins::generate(std::vector<test_event_entry>& e
|
|||
|
||||
std::vector<tx_destination_entry> destinations;
|
||||
for (size_t i = 0; i < 5; ++i)
|
||||
destinations.push_back(tx_destination_entry(m_unique_amount, alice_acc.get_public_address()));
|
||||
destinations.push_back(tx_destination_entry(unique_amount_alice, alice_acc.get_public_address()));
|
||||
|
||||
transaction tx_0 = AUTO_VAL_INIT(tx_0);
|
||||
r = construct_tx_to_key(events, tx_0, blk_0r, miner_acc, destinations, TESTS_DEFAULT_FEE, 0, 0, extra);
|
||||
CHECK_AND_ASSERT_MES(r, false, "construct_tx failed");
|
||||
events.push_back(tx_0);
|
||||
|
||||
// tx_1 : miner -> Bob
|
||||
extra.clear();
|
||||
uint64_t ut2_unlock_time = 100; // locked until block 100
|
||||
etc_tx_details_unlock_time2 ut2 = AUTO_VAL_INIT(ut2);
|
||||
destinations.clear();
|
||||
for (size_t i = 0; i < 5; ++i)
|
||||
{
|
||||
destinations.push_back(tx_destination_entry(unique_amount_bob, bob_acc.get_public_address()));
|
||||
ut2.unlock_time_array.push_back(ut2_unlock_time);
|
||||
}
|
||||
ut2.unlock_time_array.push_back(ut2_unlock_time);
|
||||
extra.push_back(ut2);
|
||||
transaction tx_1 = AUTO_VAL_INIT(tx_1);
|
||||
r = construct_tx_to_key(events, tx_1, blk_0r, miner_acc, destinations, TESTS_DEFAULT_FEE, 0, 0, extra);
|
||||
CHECK_AND_ASSERT_MES(r, false, "construct_tx failed");
|
||||
events.push_back(tx_1);
|
||||
|
||||
MAKE_NEXT_BLOCK_TX1(events, blk_1, blk_0r, miner_acc, tx_0);
|
||||
|
||||
DO_CALLBACK_PARAMS(events, "check_outputs_with_unique_amount", static_cast<size_t>(5));
|
||||
// block with tx_1 should be rejected because etc_tx_details_unlock_time2 is not allowed prior to hardfork 1
|
||||
DO_CALLBACK(events, "mark_invalid_block");
|
||||
MAKE_NEXT_BLOCK_TX1(events, blk_1b, blk_1, miner_acc, tx_1);
|
||||
|
||||
REWIND_BLOCKS_N_WITH_TIME(events, blk_1r, blk_1, miner_acc, CURRENCY_MINED_MONEY_UNLOCK_WINDOW);
|
||||
|
||||
block blk_0a;
|
||||
DO_CALLBACK_PARAMS(events, "check_outputs_with_unique_amount", unique_amount_params(unique_amount_alice, 5) );
|
||||
|
||||
// make sure outputs with m_unique_amount are still locked
|
||||
r = false;
|
||||
try
|
||||
{
|
||||
crypto::hash prev_id = get_block_hash(blk_0);
|
||||
size_t height = get_block_height(blk_0) + 1;
|
||||
MAKE_TX(events, tx_1_bad, alice_acc, miner_acc, unique_amount_alice - TESTS_DEFAULT_FEE, blk_1r);
|
||||
}
|
||||
catch (std::runtime_error&)
|
||||
{
|
||||
r = true;
|
||||
}
|
||||
CHECK_AND_ASSERT_MES(r, false, "exception was not cought as expected");
|
||||
|
||||
// try to make a PoS block with locked stake before the hardfork
|
||||
|
||||
block blk_2b;
|
||||
{
|
||||
const block& prev_block = blk_1r;
|
||||
const transaction& stake = tx_0;
|
||||
|
||||
crypto::hash prev_id = get_block_hash(prev_block);
|
||||
size_t height = get_block_height(prev_block) + 1;
|
||||
currency::wide_difficulty_type diff = generator.get_difficulty_for_next_block(prev_id, false);
|
||||
|
||||
const transaction& stake = blk_0.miner_tx;
|
||||
crypto::public_key stake_tx_pub_key = get_tx_pub_key_from_extra(stake);
|
||||
size_t stake_output_idx = 0;
|
||||
size_t stake_output_gidx = 0;
|
||||
uint64_t stake_output_amount = stake.vout[stake_output_idx].amount;
|
||||
crypto::key_image stake_output_key_image;
|
||||
keypair kp;
|
||||
generate_key_image_helper(miner_acc.get_keys(), stake_tx_pub_key, stake_output_idx, kp, stake_output_key_image);
|
||||
generate_key_image_helper(alice_acc.get_keys(), stake_tx_pub_key, stake_output_idx, kp, stake_output_key_image);
|
||||
crypto::public_key stake_output_pubkey = boost::get<txout_to_key>(stake.vout[stake_output_idx].target).key;
|
||||
|
||||
pos_block_builder pb;
|
||||
pb.step1_init_header(height, prev_id);
|
||||
pb.step2_set_txs(std::vector<transaction>());
|
||||
pb.step3_build_stake_kernel(stake_output_amount, stake_output_gidx, stake_output_key_image, diff, prev_id, null_hash, blk_0r.timestamp);
|
||||
pb.step4_generate_coinbase_tx(generator.get_timestamps_median(prev_id), generator.get_already_generated_coins(blk_0r), miner_acc.get_public_address());
|
||||
pb.step5_sign(stake_tx_pub_key, stake_output_idx, stake_output_pubkey, miner_acc);
|
||||
blk_0a = pb.m_block;
|
||||
pb.step3_build_stake_kernel(stake_output_amount, stake_output_gidx, stake_output_key_image, diff, prev_id, null_hash, prev_block.timestamp);
|
||||
pb.step4_generate_coinbase_tx(generator.get_timestamps_median(prev_id), generator.get_already_generated_coins(prev_block), miner_acc.get_public_address());
|
||||
pb.step5_sign(stake_tx_pub_key, stake_output_idx, stake_output_pubkey, alice_acc);
|
||||
blk_2b = pb.m_block;
|
||||
}
|
||||
|
||||
// it should not be accepted, because stake coins is still locked
|
||||
DO_CALLBACK(events, "mark_invalid_block");
|
||||
events.push_back(blk_2b);
|
||||
|
||||
MAKE_NEXT_BLOCK(events, blk_2, blk_1r, miner_acc);
|
||||
MAKE_NEXT_BLOCK(events, blk_3, blk_2, miner_acc);
|
||||
// make sure hardfork went okay
|
||||
CHECK_AND_ASSERT_MES(blk_2.major_version != CURRENT_BLOCK_MAJOR_VERSION && blk_3.major_version == CURRENT_BLOCK_MAJOR_VERSION, false, "hardfork did not happen as expected");
|
||||
|
||||
|
||||
// try to make a PoS block with locked stake after the hardfork
|
||||
|
||||
block blk_4b;
|
||||
{
|
||||
const block& prev_block = blk_3;
|
||||
const transaction& stake = tx_0;
|
||||
|
||||
crypto::hash prev_id = get_block_hash(prev_block);
|
||||
size_t height = get_block_height(prev_block) + 1;
|
||||
currency::wide_difficulty_type diff = generator.get_difficulty_for_next_block(prev_id, false);
|
||||
|
||||
crypto::public_key stake_tx_pub_key = get_tx_pub_key_from_extra(stake);
|
||||
size_t stake_output_idx = 0;
|
||||
size_t stake_output_gidx = 0;
|
||||
uint64_t stake_output_amount = stake.vout[stake_output_idx].amount;
|
||||
crypto::key_image stake_output_key_image;
|
||||
keypair kp;
|
||||
generate_key_image_helper(alice_acc.get_keys(), stake_tx_pub_key, stake_output_idx, kp, stake_output_key_image);
|
||||
crypto::public_key stake_output_pubkey = boost::get<txout_to_key>(stake.vout[stake_output_idx].target).key;
|
||||
|
||||
pos_block_builder pb;
|
||||
pb.step1_init_header(height, prev_id);
|
||||
pb.m_block.major_version = CURRENT_BLOCK_MAJOR_VERSION;
|
||||
pb.step2_set_txs(std::vector<transaction>());
|
||||
pb.step3_build_stake_kernel(stake_output_amount, stake_output_gidx, stake_output_key_image, diff, prev_id, null_hash, prev_block.timestamp);
|
||||
pb.step4_generate_coinbase_tx(generator.get_timestamps_median(prev_id), generator.get_already_generated_coins(prev_block), miner_acc.get_public_address());
|
||||
pb.step5_sign(stake_tx_pub_key, stake_output_idx, stake_output_pubkey, alice_acc);
|
||||
blk_4b = pb.m_block;
|
||||
}
|
||||
|
||||
// it should not be accepted, because stake coins is still locked
|
||||
DO_CALLBACK(events, "mark_invalid_block");
|
||||
events.push_back(blk_4b);
|
||||
|
||||
// blk_4 with tx_1 (etc_tx_details_unlock_time2) should be accepted after hardfork 1
|
||||
MAKE_NEXT_BLOCK_TX1(events, blk_4, blk_3, miner_acc, tx_1);
|
||||
|
||||
block prev = blk_4;
|
||||
for(size_t i = 0; i < CURRENCY_MINED_MONEY_UNLOCK_WINDOW; ++i)
|
||||
{
|
||||
MAKE_NEXT_POS_BLOCK(events, b, prev, miner_acc, std::list<currency::account_base>{miner_acc});
|
||||
prev = b;
|
||||
}
|
||||
|
||||
|
||||
//REWIND_BLOCKS_N_WITH_TIME(events, blk_4r, blk_4, miner_acc, CURRENCY_MINED_MONEY_UNLOCK_WINDOW);
|
||||
|
||||
block blk_5;
|
||||
{
|
||||
const block& prev_block = prev;
|
||||
const transaction& stake = tx_1;
|
||||
|
||||
crypto::hash prev_id = get_block_hash(prev_block);
|
||||
size_t height = get_block_height(prev_block) + 1;
|
||||
currency::wide_difficulty_type diff = generator.get_difficulty_for_next_block(prev_id, false);
|
||||
|
||||
crypto::public_key stake_tx_pub_key = get_tx_pub_key_from_extra(stake);
|
||||
size_t stake_output_idx = 0;
|
||||
size_t stake_output_gidx = 0;
|
||||
uint64_t stake_output_amount = stake.vout[stake_output_idx].amount;
|
||||
crypto::key_image stake_output_key_image;
|
||||
keypair kp;
|
||||
generate_key_image_helper(bob_acc.get_keys(), stake_tx_pub_key, stake_output_idx, kp, stake_output_key_image);
|
||||
crypto::public_key stake_output_pubkey = boost::get<txout_to_key>(stake.vout[stake_output_idx].target).key;
|
||||
|
||||
pos_block_builder pb;
|
||||
pb.step1_init_header(height, prev_id);
|
||||
pb.m_block.major_version = CURRENT_BLOCK_MAJOR_VERSION;
|
||||
pb.step2_set_txs(std::vector<transaction>());
|
||||
pb.step3_build_stake_kernel(stake_output_amount, stake_output_gidx, stake_output_key_image, diff, prev_id, null_hash, prev_block.timestamp);
|
||||
pb.step4_generate_coinbase_tx(generator.get_timestamps_median(prev_id), generator.get_already_generated_coins(prev_block), miner_acc.get_public_address());
|
||||
pb.step5_sign(stake_tx_pub_key, stake_output_idx, stake_output_pubkey, bob_acc);
|
||||
blk_5 = pb.m_block;
|
||||
}
|
||||
|
||||
// it should not be accepted, because stake coins is still locked
|
||||
DO_CALLBACK(events, "mark_invalid_block");
|
||||
events.push_back(blk_5);
|
||||
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool hard_fork_1_pos_and_locked_coins::check_outputs_with_unique_amount(currency::core& c, size_t ev_index, const std::vector<test_event_entry>& events)
|
||||
{
|
||||
size_t expected_outputs_count = 0;
|
||||
unique_amount_params p(0, 0);
|
||||
const std::string& params = boost::get<callback_entry>(events[ev_index]).callback_params;
|
||||
CHECK_AND_ASSERT_MES(epee::string_tools::hex_to_pod(params, expected_outputs_count), false, "hex_to_pod failed, params = " << params);
|
||||
CHECK_AND_ASSERT_MES(epee::string_tools::hex_to_pod(params, p), false, "hex_to_pod failed, params = " << params);
|
||||
|
||||
std::list<crypto::public_key> pub_keys;
|
||||
bool r = c.get_outs(m_unique_amount, pub_keys);
|
||||
bool r = c.get_outs(p.amount, pub_keys);
|
||||
|
||||
CHECK_AND_ASSERT_MES(r && pub_keys.size() == expected_outputs_count, false, "amount " << print_money_brief(m_unique_amount) << ": " << pub_keys.size() << " != " << expected_outputs_count);
|
||||
CHECK_AND_ASSERT_MES(r && pub_keys.size() == p.count, false, "amount " << print_money_brief(p.amount) << ": " << pub_keys.size() << " != " << p.count);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
hard_fork_1_pos_locked_height_vs_time::hard_fork_1_pos_locked_height_vs_time()
|
||||
: hard_fork_1_base_test(11)
|
||||
{
|
||||
}
|
||||
|
||||
bool hard_fork_1_pos_locked_height_vs_time::generate(std::vector<test_event_entry>& events) const
|
||||
{
|
||||
// Test idea: make sure it's impossible to use height-locked coins as PoS stake IF they are ts-locked (not height-locked) in some outputs
|
||||
// (because it could possibly be used to unlock coins eralier)
|
||||
|
||||
bool r = false;
|
||||
GENERATE_ACCOUNT(miner_acc);
|
||||
GENERATE_ACCOUNT(alice_acc);
|
||||
GENERATE_ACCOUNT(bob_acc);
|
||||
MAKE_GENESIS_BLOCK(events, blk_0, miner_acc, test_core_time::get_time());
|
||||
generator.set_hardfork_height(m_hardfork_height);
|
||||
DO_CALLBACK(events, "configure_core");
|
||||
REWIND_BLOCKS_N_WITH_TIME(events, blk_0r, blk_0, miner_acc, CURRENCY_MINED_MONEY_UNLOCK_WINDOW + 1);
|
||||
|
||||
// create few locked outputs in the blockchain with unique amount
|
||||
// tx_0 : miner -> Alice, miner -> Bob
|
||||
std::vector<extra_v> extra;
|
||||
etc_tx_details_unlock_time ut = AUTO_VAL_INIT(ut);
|
||||
ut.v = 100; // locked until block 100
|
||||
extra.push_back(ut);
|
||||
|
||||
std::vector<tx_destination_entry> destinations;
|
||||
destinations.push_back(tx_destination_entry(MK_TEST_COINS(10), alice_acc.get_public_address()));
|
||||
destinations.push_back(tx_destination_entry(MK_TEST_COINS(10), bob_acc.get_public_address()));
|
||||
|
||||
transaction tx_0 = AUTO_VAL_INIT(tx_0);
|
||||
r = construct_tx_to_key(events, tx_0, blk_0r, miner_acc, destinations, TESTS_DEFAULT_FEE, 0, 0, extra);
|
||||
CHECK_AND_ASSERT_MES(r, false, "construct_tx failed");
|
||||
events.push_back(tx_0);
|
||||
|
||||
MAKE_NEXT_BLOCK_TX1(events, blk_1, blk_0r, miner_acc, tx_0); // first block after hardfork
|
||||
|
||||
// make sure hardfork went okay
|
||||
CHECK_AND_ASSERT_MES(blk_0r.major_version != CURRENT_BLOCK_MAJOR_VERSION && blk_1.major_version == CURRENT_BLOCK_MAJOR_VERSION, false, "hardfork did not happen as expected");
|
||||
|
||||
REWIND_BLOCKS_N_WITH_TIME(events, blk_1r, blk_1, miner_acc, CURRENCY_MINED_MONEY_UNLOCK_WINDOW + 1);
|
||||
|
||||
block blk_s;
|
||||
{
|
||||
const block& prev_block = blk_1r;
|
||||
const transaction& stake = tx_0;
|
||||
const account_base& stakeholder = alice_acc;
|
||||
|
||||
crypto::hash prev_id = get_block_hash(prev_block);
|
||||
size_t height = get_block_height(prev_block) + 1;
|
||||
currency::wide_difficulty_type diff = generator.get_difficulty_for_next_block(prev_id, false);
|
||||
|
||||
crypto::public_key stake_tx_pub_key = get_tx_pub_key_from_extra(stake);
|
||||
size_t stake_output_idx = 0;
|
||||
size_t stake_output_gidx = 0;
|
||||
uint64_t stake_output_amount = stake.vout[stake_output_idx].amount;
|
||||
crypto::key_image stake_output_key_image;
|
||||
keypair kp;
|
||||
generate_key_image_helper(stakeholder.get_keys(), stake_tx_pub_key, stake_output_idx, kp, stake_output_key_image);
|
||||
crypto::public_key stake_output_pubkey = boost::get<txout_to_key>(stake.vout[stake_output_idx].target).key;
|
||||
|
||||
pos_block_builder pb;
|
||||
pb.step1_init_header(height, prev_id);
|
||||
pb.m_block.major_version = CURRENT_BLOCK_MAJOR_VERSION;
|
||||
pb.step2_set_txs(std::vector<transaction>());
|
||||
pb.step3_build_stake_kernel(stake_output_amount, stake_output_gidx, stake_output_key_image, diff, prev_id, null_hash, prev_block.timestamp);
|
||||
pb.step4_generate_coinbase_tx(generator.get_timestamps_median(prev_id), generator.get_already_generated_coins(prev_block), miner_acc.get_public_address());
|
||||
|
||||
// set etc_tx_details_unlock_time2
|
||||
remove_unlock_v1_entries_from_extra(pb.m_block.miner_tx.extra); // clear already set unlock
|
||||
std::vector<extra_v> extra;
|
||||
etc_tx_details_unlock_time2 ut2 = AUTO_VAL_INIT(ut2);
|
||||
ut2.unlock_time_array.push_back(height + CURRENCY_MINED_MONEY_UNLOCK_WINDOW); // reward lock
|
||||
for(size_t i = 0; i < pb.m_block.miner_tx.vout.size() - 1; ++i)
|
||||
ut2.unlock_time_array.push_back(test_core_time::get_time() - 1000); // stake locked by time and it's already passed
|
||||
extra.push_back(ut2);
|
||||
pb.m_block.miner_tx.extra.push_back(ut2);
|
||||
|
||||
pb.step5_sign(stake_tx_pub_key, stake_output_idx, stake_output_pubkey, stakeholder);
|
||||
blk_s = pb.m_block;
|
||||
}
|
||||
|
||||
DO_CALLBACK(events, "mark_invalid_block"); // should not pass as using time-locking in outputs
|
||||
events.push_back(blk_s);
|
||||
|
||||
block blk_good;
|
||||
{
|
||||
const block& prev_block = blk_1r;
|
||||
const transaction& stake = tx_0;
|
||||
const account_base& stakeholder = alice_acc;
|
||||
|
||||
crypto::hash prev_id = get_block_hash(prev_block);
|
||||
size_t height = get_block_height(prev_block) + 1;
|
||||
currency::wide_difficulty_type diff = generator.get_difficulty_for_next_block(prev_id, false);
|
||||
|
||||
crypto::public_key stake_tx_pub_key = get_tx_pub_key_from_extra(stake);
|
||||
size_t stake_output_idx = 0;
|
||||
size_t stake_output_gidx = 0;
|
||||
uint64_t stake_output_amount = stake.vout[stake_output_idx].amount;
|
||||
crypto::key_image stake_output_key_image;
|
||||
keypair kp;
|
||||
generate_key_image_helper(stakeholder.get_keys(), stake_tx_pub_key, stake_output_idx, kp, stake_output_key_image);
|
||||
crypto::public_key stake_output_pubkey = boost::get<txout_to_key>(stake.vout[stake_output_idx].target).key;
|
||||
|
||||
pos_block_builder pb;
|
||||
pb.step1_init_header(height, prev_id);
|
||||
pb.m_block.major_version = CURRENT_BLOCK_MAJOR_VERSION;
|
||||
pb.step2_set_txs(std::vector<transaction>());
|
||||
pb.step3_build_stake_kernel(stake_output_amount, stake_output_gidx, stake_output_key_image, diff, prev_id, null_hash, prev_block.timestamp);
|
||||
pb.step4_generate_coinbase_tx(generator.get_timestamps_median(prev_id), generator.get_already_generated_coins(prev_block), miner_acc.get_public_address());
|
||||
|
||||
// set etc_tx_details_unlock_time2
|
||||
remove_unlock_v1_entries_from_extra(pb.m_block.miner_tx.extra); // clear already set unlock
|
||||
std::vector<extra_v> extra;
|
||||
etc_tx_details_unlock_time2 ut2 = AUTO_VAL_INIT(ut2);
|
||||
ut2.unlock_time_array.push_back(height + CURRENCY_MINED_MONEY_UNLOCK_WINDOW); // reward lock
|
||||
for(size_t i = 0; i < pb.m_block.miner_tx.vout.size() - 1; ++i)
|
||||
ut2.unlock_time_array.push_back(100); // stake locked by height 100
|
||||
extra.push_back(ut2);
|
||||
pb.m_block.miner_tx.extra.push_back(ut2);
|
||||
|
||||
pb.step5_sign(stake_tx_pub_key, stake_output_idx, stake_output_pubkey, stakeholder);
|
||||
blk_good = pb.m_block;
|
||||
}
|
||||
|
||||
// should be okay
|
||||
events.push_back(blk_good);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -45,6 +45,10 @@ struct hard_fork_1_pos_and_locked_coins : public hard_fork_1_base_test
|
|||
bool generate(std::vector<test_event_entry>& events) const;
|
||||
|
||||
bool check_outputs_with_unique_amount(currency::core& c, size_t ev_index, const std::vector<test_event_entry>& events);
|
||||
|
||||
uint64_t m_unique_amount;
|
||||
};
|
||||
|
||||
struct hard_fork_1_pos_locked_height_vs_time : public hard_fork_1_base_test
|
||||
{
|
||||
hard_fork_1_pos_locked_height_vs_time();
|
||||
bool generate(std::vector<test_event_entry>& events) const;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -169,11 +169,19 @@ IF %ERRORLEVEL% NEQ 0 (
|
|||
@echo "---------------------------------------------------------------"
|
||||
@echo "---------------------------------------------------------------"
|
||||
|
||||
@echo " UPLOADING TO SERVER ...."
|
||||
|
||||
set installer_file=%ACHIVE_NAME_PREFIX%%version%-installer.exe
|
||||
set installer_path=%BUILDS_PATH%\builds\%installer_file%
|
||||
|
||||
@echo " SIGNING ...."
|
||||
|
||||
%ZANO_SIGN_CMD% %installer_path%
|
||||
IF %ERRORLEVEL% NEQ 0 (
|
||||
@echo "failed to sign installer"
|
||||
goto error
|
||||
)
|
||||
|
||||
@echo " UPLOADING TO SERVER ...."
|
||||
|
||||
pscp -load zano_build_server %installer_path% build.zano.org:/var/www/html/builds
|
||||
IF %ERRORLEVEL% NEQ 0 (
|
||||
@echo "FAILED TO UPLOAD EXE TO SERVER"
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue