<oembed><type>rich</type><version>1.0</version><author_name>npub1tjephawh7fdf6358jufuh5eyxwauzrjqa7qn50pglee4tayc2ntqcjtl6r</author_name><author_url>https://nostr.ae/npub1tjephawh7fdf6358jufuh5eyxwauzrjqa7qn50pglee4tayc2ntqcjtl6r</author_url><provider_name>njump</provider_name><provider_url>https://nostr.ae</provider_url><html>📅 Original date posted:2016-05-09&#xA;📝 Original message:On 05/03/2016 12:13 AM, lf-lists at mattcorallo.com (Matt Corallo) wrote:&#xA;&gt; Hi all,&#xA;&gt; &#xA;&gt; The following is a BIP-formatted design spec for compact block relay&#xA;&gt; designed to limit on wire bytes during block relay. You can find the&#xA;&gt; latest version of this document at&#xA;&gt; https://github.com/TheBlueMatt/bips/blob/master/bip-TODO.mediawiki.&#xA;&#xA;Hi Matt,&#xA;&#xA;thank you for working on this!&#xA;&#xA;&gt; ===New data structures===&#xA;&gt; Several new data structures are added to the P2P network to relay&#xA;&gt; compact blocks: PrefilledTransaction, HeaderAndShortIDs,&#xA;&gt; BlockTransactionsRequest, and BlockTransactions. Additionally, we&#xA;&gt; introduce a new variable-length integer encoding for use in these data&#xA;&gt; structures.&#xA;&gt; &#xA;&gt; For the purposes of this section, CompactSize refers to the&#xA;&gt; variable-length integer encoding used across the existing P2P protocol&#xA;&gt; to encode array lengths, among other things, in 1, 3, 5 or 9 bytes.&#xA;&#xA;This is a not, but I think it&#39;s a bit strange to have two separate&#xA;variable length integers in the same specification. I understand is one&#xA;is already the default for variable-length integers currently, and there&#xA;are reasons to use the other one for efficiency reasons in some places,&#xA;but perhaps we should aim to get everything using the latter?&#xA;&#xA;&gt; ====New VarInt====&#xA;&gt; Variable-length integers: bytes are a MSB base-128 encoding of the number.&#xA;&gt; The high bit in each byte signifies whether another digit follows. To make&#xA;&gt; sure the encoding is one-to-one, one is subtracted from all but the last&#xA;&gt; digit.&#xA;&#xA;Maybe it&#39;s worth mentioning that it is based on ASN.1 BER&#39;s compressed&#xA;integer format (see&#xA;https://www.itu.int/ITU-T/studygroups/com17/languages/X.690-0207.pdf&#xA;section 8.1.3.5), though with a small modification to make every integer&#xA;have a single unique encoding.&#xA;&#xA;&gt; ====HeaderAndShortIDs====&#xA;&gt; A HeaderAndShortIDs structure is used to relay a block header, the short&#xA;&gt; transactions IDs used for matching already-available transactions, and a&#xA;&gt; select few transactions which we expect a peer may be missing.&#xA;&gt; &#xA;&gt; |shortids||List of uint64_ts||8*shortids_length bytes||Little&#xA;&gt; Endian||The short transaction IDs calculated from the transactions which&#xA;&gt; were not provided explicitly in prefilledtxn&#xA;&#xA;I tried to derive what length of short ids is actually necessary (some&#xA;write-up is on&#xA;https://gist.github.com/sipa/b2eb2e486156b5509ac711edd16153ed but it&#39;s&#xA;incomplete).&#xA;&#xA;For any reasonable numbers I can come up with (in a very wide range),&#xA;the number of bits needed is very well approximated by:&#xA;&#xA;  log2(#receiver_mempool_txn * #block_txn_not_in_receiver_mempool /&#xA;acceptable_per_block_failure_rate)&#xA;&#xA;For example, with 20000 mempool transactions, 2500 transactions in a&#xA;block, 95% hitrate, and a chance of 1 in 10000 blocks to fail to&#xA;reconstruct, needed_bits = log2(20000 * 2500 * (1 - 0.95) / 0.0001) =&#xA;34.54, or 5 byte txids would suffice.&#xA;&#xA;Note that 1 in 10000 failures may sound like a lot, but this is for each&#xA;individual connection, and since every transmission uses separately&#xA;salted identifiers, occasional failures should not affect global&#xA;propagation. Given that transmission failures due to timeouts, network&#xA;connectivity, ... already occur much more frequently than once every few&#xA;gigabytes (what 10000 blocks corresponds to), that&#39;s probably already&#xA;more than enough.&#xA;&#xA;In short: I believe 5 or 6 byte txids should be enough, but perhaps it&#xA;makes sense to allow the sender to choose (so he can weigh trying&#xA;multiple nonces against increasing the short txid length).&#xA;&#xA;&gt; ====Short transaction IDs====&#xA;&gt; Short transaction IDs are used to represent a transaction without&#xA;&gt; sending a full 256-bit hash. They are calculated by:&#xA;&gt; # single-SHA256 hashing the block header with the nonce appended (in&#xA;&gt; little-endian)&#xA;&gt; # XORing each 8-byte chunk of the double-SHA256 transaction hash with&#xA;&gt; each corresponding 8-byte chunk of the hash from the previous step&#xA;&gt; # Adding each of the XORed 8-byte chunks together (in little-endian)&#xA;&gt; iteratively to find the short transaction ID&#xA;&#xA;An alternative would be using SipHash-1-3 (a form of SipHash with&#xA;reduced iteration counts; the default is SipHash-2-4). SipHash was&#xA;designed as a Message Authentication Code, where the security&#xA;requirements are much stronger than in our case (in particular, we don&#39;t&#xA;care about observers being able to finding the key, as the key is just&#xA;public knowledge here). One of the designers of SipHash has commented&#xA;that SipHash-1-3 for collision resistance in hash tables may be enough:&#xA;https://github.com/rust-lang/rust/issues/29754#issuecomment-156073946&#xA;&#xA;Using SipHash-1-3 on modern hardware would take ~32 CPU cycles per txid.&#xA;&#xA;&gt; ===Implementation Notes===&#xA;&#xA;There are a few more heuristics that MAY be used to improve performance:&#xA;&#xA;* Receivers should treat short txids in blocks that match multiple&#xA;mempool transactions as non-matches, and request the transactions. This&#xA;significantly reduces the failure to reconstruct.&#xA;&#xA;* When constructing a compact block to send, the sender can verify it&#xA;against its own mempool to check for collisions, and if so, choose to&#xA;either try another nonce, or increase the short txid length.&#xA;&#xA;Cheers,&#xA;&#xA;-- &#xA;Pieter</html></oembed>