diff --git a/chain/src/txhashset.rs b/chain/src/txhashset.rs index e5bd27db4..42da28fb3 100644 --- a/chain/src/txhashset.rs +++ b/chain/src/txhashset.rs @@ -565,15 +565,15 @@ impl<'a> Extension<'a> { .unwrap_or(0); if pos > 0 { - // If we have not yet reached 1,000 blocks then + // If we have not yet reached 1,000 / 1,440 blocks then // we can fail immediately as coinbase cannot be mature. - if height < global::coinbase_maturity() { + if height < global::coinbase_maturity(height) { return Err(ErrorKind::ImmatureCoinbase.into()); } // Find the "cutoff" pos in the output MMR based on the // header from 1,000 blocks ago. - let cutoff_height = height.checked_sub(global::coinbase_maturity()).unwrap_or(0); + let cutoff_height = height.checked_sub(global::coinbase_maturity(height)).unwrap_or(0); let cutoff_header = self.commit_index.get_header_by_height(cutoff_height)?; let cutoff_pos = cutoff_header.output_mmr_size; diff --git a/chain/tests/test_coinbase_maturity.rs b/chain/tests/test_coinbase_maturity.rs index 441e93dd0..ab351ecb5 100644 --- a/chain/tests/test_coinbase_maturity.rs +++ b/chain/tests/test_coinbase_maturity.rs @@ -98,7 +98,7 @@ fn test_coinbase_maturity() { let amount = consensus::REWARD; - let lock_height = 1 + global::coinbase_maturity(); + let lock_height = 1 + global::coinbase_maturity(1); assert_eq!(lock_height, 4); // here we build a tx that attempts to spend the earlier coinbase output diff --git a/core/src/consensus.rs b/core/src/consensus.rs index 58c6db9b0..fb4fc992f 100644 --- a/core/src/consensus.rs +++ b/core/src/consensus.rs @@ -41,15 +41,16 @@ pub fn reward(fee: u64) -> u64 { REWARD + fee } -/// Number of blocks before a coinbase matures and can be spent -pub const COINBASE_MATURITY: u64 = 1_000; - /// Block interval, in seconds, the network will tune its next_target for. Note /// that we may reduce this value in the future as we get more data on mining /// with Cuckoo Cycle, networks improve and block propagation is optimized /// (adjusting the reward accordingly). pub const BLOCK_TIME_SEC: u64 = 60; +/// Number of blocks before a coinbase matures and can be spent +/// set to nominal number of block in one day (1440 with 1-minute blocks) +pub const COINBASE_MATURITY: u64 = 24 * 60 * 60 / BLOCK_TIME_SEC; + /// Cuckoo-cycle proof size (cycle length) pub const PROOFSIZE: usize = 42; diff --git a/core/src/global.rs b/core/src/global.rs index 357c05cd9..91c9dcfb6 100644 --- a/core/src/global.rs +++ b/core/src/global.rs @@ -50,6 +50,12 @@ pub const AUTOMATED_TESTING_COINBASE_MATURITY: u64 = 3; /// User testing coinbase maturity pub const USER_TESTING_COINBASE_MATURITY: u64 = 3; +/// Old coinbase maturity +/// TODO: obsolete for mainnet together with maturity code below +pub const OLD_COINBASE_MATURITY: u64 = 1_000; +/// soft-fork around Sep 17 2018 on testnet3 +pub const COINBASE_MATURITY_FORK_HEIGHT: u64 = 100_000; + /// Testing cut through horizon in blocks pub const TESTING_CUT_THROUGH_HORIZON: u32 = 20; @@ -133,13 +139,14 @@ pub fn proofsize() -> usize { } } -/// Coinbase maturity -pub fn coinbase_maturity() -> u64 { +/// Coinbase maturity for coinbases to be spent at given height +pub fn coinbase_maturity(height: u64) -> u64 { let param_ref = CHAIN_TYPE.read().unwrap(); match *param_ref { ChainTypes::AutomatedTesting => AUTOMATED_TESTING_COINBASE_MATURITY, ChainTypes::UserTesting => USER_TESTING_COINBASE_MATURITY, - _ => COINBASE_MATURITY, + _ => if height < COINBASE_MATURITY_FORK_HEIGHT { OLD_COINBASE_MATURITY } + else { COINBASE_MATURITY }, } } diff --git a/wallet/src/libwallet/internal/restore.rs b/wallet/src/libwallet/internal/restore.rs index 82c3a2ef9..05913de04 100644 --- a/wallet/src/libwallet/internal/restore.rs +++ b/wallet/src/libwallet/internal/restore.rs @@ -74,7 +74,7 @@ where ); let lock_height = if *is_coinbase { - *height + global::coinbase_maturity() + *height + global::coinbase_maturity(*height) // ignores on/off spendability around soft fork height } else { *height }; diff --git a/wallet/src/libwallet/internal/updater.rs b/wallet/src/libwallet/internal/updater.rs index d82f9eacb..4de8673ff 100644 --- a/wallet/src/libwallet/internal/updater.rs +++ b/wallet/src/libwallet/internal/updater.rs @@ -383,7 +383,7 @@ where let root_key_id = wallet.keychain().root_key_id(); let height = block_fees.height; - let lock_height = height + global::coinbase_maturity(); + let lock_height = height + global::coinbase_maturity(height); // ignores on/off spendability around soft fork height let key_id = block_fees.key_id(); let (key_id, derivation) = match key_id { diff --git a/wallet/tests/transaction.rs b/wallet/tests/transaction.rs index 52dcfc4e7..dc8b973c8 100644 --- a/wallet/tests/transaction.rs +++ b/wallet/tests/transaction.rs @@ -90,7 +90,7 @@ fn basic_transaction_api( // few values to keep things shorter let reward = core::consensus::REWARD; - let cm = global::coinbase_maturity(); + let cm = global::coinbase_maturity(0); // assume all testing precedes soft fork height // mine a few blocks let _ = common::award_blocks_to_wallet(&chain, wallet1.clone(), 10); @@ -288,7 +288,7 @@ fn tx_rollback(test_dir: &str, backend_type: common::BackendType) -> Result<(), // few values to keep things shorter let reward = core::consensus::REWARD; - let cm = global::coinbase_maturity(); + let cm = global::coinbase_maturity(0); // assume all testing precedes soft fork height // mine a few blocks let _ = common::award_blocks_to_wallet(&chain, wallet1.clone(), 5);