add block validation consensus rule for block coinbase output

and kernel counts
This commit is contained in:
antiochp 2018-01-22 13:45:47 -05:00
parent ba4c450d2f
commit ecda870d70
No known key found for this signature in database
GPG key ID: 49CBDBCE8AB061C1
2 changed files with 32 additions and 7 deletions

View file

@ -44,6 +44,16 @@ pub fn reward(fee: u64) -> u64 {
/// Number of blocks before a coinbase matures and can be spent /// Number of blocks before a coinbase matures and can be spent
pub const COINBASE_MATURITY: u64 = 1_000; pub const COINBASE_MATURITY: u64 = 1_000;
/// Max number of coinbase outputs in a valid block.
/// This is to prevent a miner generating an excessively large "compact block".
/// But we do techincally support blocks with multiple coinbase outputs/kernels.
pub const MAX_BLOCK_COINBASE_OUTPUTS: u64 = 1;
/// Max number of coinbase kernels in a valid block.
/// This is to prevent a miner generating an excessively large "compact block".
/// But we do techincally support blocks with multiple coinbase outputs/kernels.
pub const MAX_BLOCK_COINBASE_KERNELS: u64 = 1;
/// Block interval, in seconds, the network will tune its next_target for. Note /// 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 /// 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 /// with Cuckoo Cycle, networks improve and block propagation is optimized
@ -209,7 +219,7 @@ where
let end_ts = window_end[window_end.len() / 2]; let end_ts = window_end[window_end.len() / 2];
// Average difficulty and dampened average time // Average difficulty and dampened average time
let diff_avg = diff_sum.into_num() as f64 / let diff_avg = diff_sum.into_num() as f64 /
Difficulty::from_num(DIFFICULTY_ADJUST_WINDOW).into_num() as f64; Difficulty::from_num(DIFFICULTY_ADJUST_WINDOW).into_num() as f64;
let ts_damp = (3 * BLOCK_TIME_WINDOW + (begin_ts - end_ts)) / 4; let ts_damp = (3 * BLOCK_TIME_WINDOW + (begin_ts - end_ts)) / 4;
@ -223,7 +233,7 @@ where
}; };
let difficulty = let difficulty =
diff_avg * Difficulty::from_num(BLOCK_TIME_WINDOW).into_num() as f64 diff_avg * Difficulty::from_num(BLOCK_TIME_WINDOW).into_num() as f64
/ Difficulty::from_num(adj_ts).into_num() as f64; / Difficulty::from_num(adj_ts).into_num() as f64;
// All this ceil and f64 business is so that difficulty can always adjust // All this ceil and f64 business is so that difficulty can always adjust
// for smaller numbers < 10 // for smaller numbers < 10

View file

@ -73,6 +73,10 @@ pub enum Error {
/// The lock_height needed to be reached for the coinbase output to mature /// The lock_height needed to be reached for the coinbase output to mature
lock_height: u64, lock_height: u64,
}, },
/// Limit on number of coinbase outputs in a valid block.
CoinbaseOutputCountExceeded,
/// Limit on number of coinbase kernels in a valid block.
CoinbaseKernelCountExceeded,
/// Other unspecified error condition /// Other unspecified error condition
Other(String) Other(String)
} }
@ -674,11 +678,12 @@ impl Block {
Ok(()) Ok(())
} }
// Validate the coinbase outputs generated by miners. Entails 2 main checks: /// Validate the coinbase outputs generated by miners. Entails 3 main checks:
// ///
// * That the sum of all coinbase-marked outputs equal the supply. /// * That the block does not exceed the number of permitted coinbase outputs or kernels.
// * That the sum of blinding factors for all coinbase-marked outputs match /// * That the sum of all coinbase-marked outputs equal the supply.
// the coinbase-marked kernels. /// * That the sum of blinding factors for all coinbase-marked outputs match
/// the coinbase-marked kernels.
fn verify_coinbase(&self) -> Result<(), Error> { fn verify_coinbase(&self) -> Result<(), Error> {
let cb_outs = self.outputs let cb_outs = self.outputs
.iter() .iter()
@ -692,6 +697,16 @@ impl Block {
.cloned() .cloned()
.collect::<Vec<TxKernel>>(); .collect::<Vec<TxKernel>>();
// First check that we do not have too many coinbase outputs in the block.
if cb_outs.len() as u64 > consensus::MAX_BLOCK_COINBASE_OUTPUTS {
return Err(Error::CoinbaseOutputCountExceeded);
}
// And that we do not have too many coinbase kernels in the block.
if cb_kerns.len() as u64 > consensus::MAX_BLOCK_COINBASE_KERNELS {
return Err(Error::CoinbaseKernelCountExceeded);
}
let over_commit; let over_commit;
let out_adjust_sum; let out_adjust_sum;
let kerns_sum; let kerns_sum;