Bitcoin Forum

Bitcoin => Development & Technical Discussion => Topic started by: Coding Enthusiast on February 20, 2021, 09:07:07 AM



Title: Assuming block.vtx.size() return tx count why is it used for block size check?
Post by: Coding Enthusiast on February 20, 2021, 09:07:07 AM
I'm trying to figure out what validations are being performed on block size and so far found this line:
https://github.com/bitcoin/bitcoin/blob/828bb776d29cbdfad3937ba100c428e3244c652f/src/validation.cpp#L3348
Code:
if (block.vtx.empty() || 
    block.vtx.size() * WITNESS_SCALE_FACTOR > MAX_BLOCK_WEIGHT ||
    ::GetSerializeSize(block, PROTOCOL_VERSION | SERIALIZE_TRANSACTION_NO_WITNESS) * WITNESS_SCALE_FACTOR > MAX_BLOCK_WEIGHT)

Google tells me that in c++ the size() method in std::vector (which is block.vtx type) returns item count which makes me wonder why is transaction count being multiplied by 4 and compared with max block weight?


Title: Re: Assuming block.vtx.size() return tx count why is it used for block size check?
Post by: NotATether on February 20, 2021, 11:37:20 AM
It is not measuring the size in bytes, it is measuring it in weight units. To convert from bytes to WUs you multiply  by 4. That is why WITNESS_SCALE_FACTOR is set to 4. MAX_BLOCK_WEIGHT is set to 4000000 weight units which corresponds to 1vMB blocks size.

Anyway, it looks like the second condition is just a strawman check to guard against having more transactions than what is physically possible in a block (hypothetically assuming each transaction has a 1vbyte size) and that the actual block size check is made in the third condition with GetSerializeSize().

@Coding Enthusiast I edited my answer.


Title: Re: Assuming block.vtx.size() return tx count why is it used for block size check?
Post by: Coding Enthusiast on February 20, 2021, 11:40:04 AM
That doesn't answer my question.


Title: Re: Assuming block.vtx.size() return tx count why is it used for block size check?
Post by: j2002ba2 on February 20, 2021, 11:42:18 AM
You'd have to ask Satoshi about this. Code snippet from v0.1.0 (or 0.1.3):

Code:
bool CBlock::CheckBlock() const
{
    // These are checks that are independent of context
    // that can be verified before saving an orphan block.

    // Size limits
    if (vtx.empty() || vtx.size() > MAX_SIZE || ::GetSerializeSize(*this, SER_DISK) > MAX_SIZE)
        return error("CheckBlock() : size limits failed");



Title: Re: Assuming block.vtx.size() return tx count why is it used for block size check?
Post by: vjudeu on February 20, 2021, 01:16:44 PM
This is just pure guessing, but I will share my thoughts with you:

This check is needed because minimal physically possible transaction size is one byte and because merkle tree has no size limit, without this check it would be possible to attack just by creating enormously large merkle tree. So, maybe it is redundant and maybe this case will never happen, but it is here just to make sure that if for example block size limit is 1 MB, then it should be impossible to make a block with more than one million transactions. And because merkle root is a binary tree, it is possible to check that the whole tree depth is not higher than 20.