Author

Topic: cgminer - blockchain height in coinbase transaction (Read 184 times)

member
Activity: 100
Merit: 29
Fine if somebody can come up with an explanation, but I probably won't bother again before block #8388608  Smiley
legendary
Activity: 2170
Merit: 6279
be constructive or S.T.F.U
Good question, I was thinking exactly the same. After a quick search through the Bitcoin core code, I couldn't find any reference of the height defined as signed integer either.

Maybe there are other ints in the code that have to signed and they wanted to avoid mixing both signed and unsigned ints in the same function as that would be slower than using either one on it's own.

Anyways, one of the folks who wrote that code is still somehow active in here, he 'might' be able to answer your question via PM if you really are eager to know.
member
Activity: 100
Merit: 29
Good question, I was thinking exactly the same. After a quick search through the Bitcoin core code, I couldn't find any reference of the height defined as signed integer either.
legendary
Activity: 2170
Merit: 6279
be constructive or S.T.F.U
Indeed it's a signed integer Roll Eyes Ofc, it's one bit less then...

But why? What is the need for a signed integer in this code? It is not like val can be negative in the first place, I know some operations are performed faster with signed ints in c but with todays hardware the difference is likely nothing, in fact, a few operations like division will be faster with unsigned ints.

Maybe they benched marked the code back then and so happened signed was a bit faster, which might have changed with today's hardware.

member
Activity: 100
Merit: 29
Indeed it's a signed integer Roll Eyes Ofc, it's one bit less then...

Came to think about this handling when mining on testnet. The blockchain has grown beyond 2113663 there and this code is creating an invalid height in the coinbase transaction due to the trailing zero bits special handling. So I assume the correct way is to use the full signed space instead.

Thanks for your feedback.
legendary
Activity: 2170
Merit: 6279
be constructive or S.T.F.U
Could somebody please explain why the limits for the byte length have always been set way lower than what the little-endian encoding would allow?
E.g. length 1 would allow for 255

That is just the number of combinations of bits you can have in 8 bits, so if you start with 0000-0000 all the way without duplicates, you should have a total of 256 (including 0) different sets.

That is called an unsigned 8 bit which can be represented by 2^8 - 1 = 255

The value in the code you posted is a signed integer and one bit will be used as a flag so now you have xxxx-xxx1 which can be represented as 2^7 - 1 = 127, anything above 127 will be 2 bytes and 2 bytes of unsigned int should be (2^15)-1 = -+32767 but the code says 16511 is the limit which means according to this 1 bit is used to determine the number of extra bytes which is represented in 0 in the above ( xxxx-xx10-xxxx-xxxx) and that will give you 2^14 +127 = 16511, next will be 3 bytes or  2^21 + 16511 = 2113663 and so on.

Quote
The number of trailing zero bits in the first byte indicates how many subsequent bytes there are. This allows the number of bytes in an encoded integer to be efficiently determined with a single instruction (e.g., BSF or TZCNT) on most modern processors.

Source: https://github.com/stepchowfun/typical

Edited: added more details.
member
Activity: 100
Merit: 29
Could somebody please explain why the limits for the byte length have always been set way lower than what the little-endian encoding would allow?

E.g. length 1 would allow for 255, length 2 up to 65535. Instead 128 resp. 16512 was defined as upper limit.

https://github.com/vthoang/cgminer/blob/master/util.c#L1035

Code:
/*  For encoding nHeight into coinbase, return how many bytes were used */
int ser_number(unsigned char *s, int32_t val)
{
        int32_t *i32 = (int32_t *)&s[1];
        int len;

        if (val < 128)
                len = 1;
        else if (val < 16512)
                len = 2;
        else if (val < 2113664)
                len = 3;
        else
                len = 4;
        *i32 = htole32(val);
        s[0] = len++;
        return len;
}

Edit: Comparing with kano's repo, the limit is set to half max there, which makes more sense from a consistency perspective.
Jump to: