Block size limit as a max weight

This commit is contained in:
Ignotus Peverell 2017-10-06 03:34:35 +00:00
parent 4e41365fe8
commit c7f1ce965e
No known key found for this signature in database
GPG key ID: 99CD25F39F8F8211
2 changed files with 51 additions and 2 deletions

View file

@ -62,6 +62,25 @@ pub const CUT_THROUGH_HORIZON: u32 = 48 * 3600 / (BLOCK_TIME_SEC as u32);
/// peer-to-peer networking layer only for DoS protection.
pub const MAX_MSG_LEN: u64 = 20_000_000;
/// Weight of an input when counted against the max block weigth capacity
pub const BLOCK_INPUT_WEIGHT: usize = 1;
/// Weight of an output when counted against the max block weight capacity
pub const BLOCK_OUTPUT_WEIGHT: usize = 10;
/// Weight of a kernel when counted against the max block weight capacity
pub const BLOCK_KERNEL_WEIGHT: usize = 2;
/// Total maximum block weight
pub const MAX_BLOCK_WEIGHT: usize = 80_000;
/// Whether a block exceeds the maximum acceptable weight
pub fn exceeds_weight(input_len: usize, output_len: usize, kernel_len: usize) -> bool {
input_len * BLOCK_INPUT_WEIGHT +
output_len * BLOCK_OUTPUT_WEIGHT +
kernel_len * BLOCK_KERNEL_WEIGHT > MAX_BLOCK_WEIGHT
}
/// The minimum mining difficulty we'll allow
pub const MINIMUM_DIFFICULTY: u64 = 10;

View file

@ -20,8 +20,7 @@ use std::collections::HashSet;
use core::Committed;
use core::{Input, Output, Proof, TxKernel, Transaction, COINBASE_KERNEL, COINBASE_OUTPUT};
use consensus::{REWARD, reward};
use consensus::MINIMUM_DIFFICULTY;
use consensus::{MINIMUM_DIFFICULTY, REWARD, reward, exceeds_weight};
use core::hash::{Hash, Hashed, ZERO_HASH};
use core::target::Difficulty;
use ser::{self, Readable, Reader, Writeable, Writer};
@ -46,6 +45,8 @@ pub enum Error {
CoinbaseSumMismatch,
/// Kernel fee can't be odd, due to half fee burning
OddKernelFee,
/// Too many inputs, outputs or kernels in the block
WeightExceeded,
/// Underlying Secp256k1 error (signature validation or invalid public
/// key typically)
Secp(secp::Error),
@ -425,6 +426,9 @@ impl Block {
/// additional data. Includes commitment sums and kernels, Merkle
/// trees, reward, etc.
pub fn validate(&self, secp: &Secp256k1) -> Result<(), Error> {
if exceeds_weight(self.inputs.len(), self.outputs.len(), self.kernels.len()) {
return Err(Error::WeightExceeded);
}
self.verify_coinbase(secp)?;
self.verify_kernels(secp, false)?;
Ok(())
@ -527,6 +531,8 @@ mod test {
use core::build::{self, input, output, with_fee};
use core::test::tx2i1o;
use keychain::{Identifier, Keychain};
use consensus::*;
use std::time::Instant;
use secp;
@ -545,6 +551,30 @@ mod test {
.unwrap()
}
// Too slow for now #[test]
fn too_large_block() {
let keychain = Keychain::from_random_seed().unwrap();
let max_out = MAX_BLOCK_WEIGHT / BLOCK_OUTPUT_WEIGHT;
let mut pks = vec![];
for n in 0..(max_out+1) {
pks.push(keychain.derive_pubkey(n as u32).unwrap());
}
let mut parts = vec![];
for _ in 0..max_out {
parts.push(output(5, pks.pop().unwrap()));
}
let now = Instant::now();
parts.append(&mut vec![input(500000, pks.pop().unwrap()), with_fee(2)]);
let mut tx = build::transaction(parts, &keychain).map(|(tx, _)| tx).unwrap();
println!("Build tx: {}", now.elapsed().as_secs());
let b = new_block(vec![&mut tx], &keychain);
assert!(b.validate(&keychain.secp()).is_err());
}
#[test]
// builds a block with a tx spending another and check if merging occurred
fn compactable_block() {