bitcoincashorg / spec

Technical specifications
112 stars 64 forks source link

Looks like some missed logic in the documentation. #47

Closed RichyT closed 6 years ago

RichyT commented 6 years ago

This makes no sense: The payload is composed of 3 elements:

A version byte indicating the type of address.
A hash.
A 40 bits checksum.

Then

The checksum is calculated over the following data:

The lower 5 bits of each characters of the prefix.
A zero for the separator (5 zero bits).
The payload by chunks of 5 bits. The payload is padded with zero bits up to the point where it is a multiple of 5 bits.

How can the checksum be calculated over itself?

deadalnix commented 6 years ago

Yes, the checksum is all zeros when computing the checksum. Can you make a PR to the spec ?

avl42 commented 6 years ago

I agree that the spec is not overly helpful for understanding what needs to be done - I only understood it after examining an existing implementation, and I'd almost bet that whoever wrote that one either examined an existing one, too, or was the one who designed it, themselves ;-)

The first two components are easy: assume we wanted to encode prefix "abc", that gives 1, 2, 3, 0 - each a 5bit integer, the final zero is for the separator.

Then the less trivial part: let's assume hashdata starting with "96...", prepend the versionbyte e.g. 00 for "p2kh" of size 160bits, then you get these bits: 0000 0000 1001 0110 ...

You regroup them to groups of five bits: 00000 00010 01011 0... adding just as many 0-bits as necessary to complete a 5-group.

Then the crucial part: add 8 further '00000'bit groups.

That vector of 5bit ints gets fed to the polymod function, which returns a 40-bit number.

You then split this 40bit number into eight 5-bit numbers (msb first) and then you concatenate only the vector obtained from hexdata (not the bytes from prefix nor the sep) and instead of the 8 zeroes, you add the 8 5-bit numbers from polymod's result.

Finally you map each element of that vector to the corresponding base32 char (0->q, 1->p, ...) and prepend bitcoincash: (or for the example above "abc:")

I hope that helps...

Am 16.01.2018 23:46 schrieb "RichyT" notifications@github.com:

This makes no sense: The payload is composed of 3 elements:

A version byte indicating the type of address. A hash. A 40 bits checksum.

Then

The checksum is calculated over the following data:

The lower 5 bits of each characters of the prefix. A zero for the separator (5 zero bits). The payload by chunks of 5 bits. The payload is padded with zero bits up to the point where it is a multiple of 5 bits.

How can the checksum be calculated over itself?

— You are receiving this because you are subscribed to this thread. Reply to this email directly, view it on GitHub https://github.com/Bitcoin-UAHF/spec/issues/47, or mute the thread https://github.com/notifications/unsubscribe-auth/AFAwsv_cNiKs-Sb9IB-w9aHvcwFB9sdVks5tLSbhgaJpZM4RgitB .

avl42 commented 6 years ago

PS: The existing implementation that actually helped me was the python one linked from https://gist.github.com/DesWurstes/bba4222c8b6253b940096fcede97e17a

Before seeing that, my misunderstandings were 0-padding the hash's bits at the wrong side (to the left, instead of to the right) to get a multiple of 5 bits, and not knowing about having to append the 8 zeroes.

4tochka commented 6 years ago

Python example https://github.com/bitaps-com/pybch/blob/master/pybch/tools.py#L312

RichyT commented 6 years ago

Thanks. Yes, the documentation appears to be correct but incomplete as it doesn't specify how to obtain the check digits nor what the checksum should be (It looks like it should return 1). This information is in https://github.com/bitcoin/bips/blob/master/bip-0173.mediawiki and I'll be looking at some existing implementations too, thanks for all the suggestions.

It also appears to be remiss on not specifying what end the payload is padded if the number of bits is not a multiple of 5. Probably an obvious one there but still.

RichyT commented 6 years ago

Ah, I see. It looks like the checksum is actually reversible? So you set the bits to 0 then if you get 53 out at the end, you set that as the checksum. That makes sense. I know that works for simple checksums but I didn't know it would work for this. I guess I was over-complicating it in my head.

RichyT commented 6 years ago

Thanks all.

schancel commented 6 years ago

https://github.com/Bitcoin-UAHF/spec/pull/50