import pkg/unittest2 import pkg/libp2p/cid import pkg/storage/blocktype import pkg/storage/blockexchange/protocol/message ## All Expected_* consts were generated from the minprotobuf encoder and are ## the current wire format. ## DO NOT MODIFY ## DO NOT MODIFY ## DO NOT MODIFY ## DO NOT MODIFY ## DO NOT MODIFY any of the Expected_* consts. If tests are failing after ## touching message.nim, the protobuf library, the custom Cid encoder or anything ## else in the encode path, the wire format has diverged from what ## existing peers expect and they will not be able to decode any messages. const Expected_emptyMessage = @[0x0A'u8, 0x02'u8, 0x10'u8, 0x00'u8] const Expected_wantListEmptyFullFalse = @[0x0A'u8, 0x02'u8, 0x10'u8, 0x00'u8] const Expected_wantListEmptyFullTrue = @[0x0A'u8, 0x02'u8, 0x10'u8, 0x01'u8] const Expected_wantListSingleEntry = @[ 0x0A'u8, 0x3A'u8, 0x0A'u8, 0x36'u8, 0x0A'u8, 0x28'u8, 0x0A'u8, 0x24'u8, 0x01'u8, 0x55'u8, 0x12'u8, 0x20'u8, 0x00'u8, 0x01'u8, 0x02'u8, 0x03'u8, 0x04'u8, 0x05'u8, 0x06'u8, 0x07'u8, 0x08'u8, 0x09'u8, 0x0A'u8, 0x0B'u8, 0x0C'u8, 0x0D'u8, 0x0E'u8, 0x0F'u8, 0x10'u8, 0x11'u8, 0x12'u8, 0x13'u8, 0x14'u8, 0x15'u8, 0x16'u8, 0x17'u8, 0x18'u8, 0x19'u8, 0x1A'u8, 0x1B'u8, 0x1C'u8, 0x1D'u8, 0x1E'u8, 0xAA'u8, 0x10'u8, 0x05'u8, 0x10'u8, 0x01'u8, 0x18'u8, 0x00'u8, 0x20'u8, 0x00'u8, 0x28'u8, 0x01'u8, 0x30'u8, 0x00'u8, 0x38'u8, 0x2A'u8, 0x10'u8, 0x00'u8, ] const Expected_wantListMultipleFullTrue = @[ 0x0A'u8, 0x72'u8, 0x0A'u8, 0x36'u8, 0x0A'u8, 0x28'u8, 0x0A'u8, 0x24'u8, 0x01'u8, 0x55'u8, 0x12'u8, 0x20'u8, 0x00'u8, 0x01'u8, 0x02'u8, 0x03'u8, 0x04'u8, 0x05'u8, 0x06'u8, 0x07'u8, 0x08'u8, 0x09'u8, 0x0A'u8, 0x0B'u8, 0x0C'u8, 0x0D'u8, 0x0E'u8, 0x0F'u8, 0x10'u8, 0x11'u8, 0x12'u8, 0x13'u8, 0x14'u8, 0x15'u8, 0x16'u8, 0x17'u8, 0x18'u8, 0x19'u8, 0x1A'u8, 0x1B'u8, 0x1C'u8, 0x1D'u8, 0x1E'u8, 0xAA'u8, 0x10'u8, 0x00'u8, 0x10'u8, 0x0A'u8, 0x18'u8, 0x00'u8, 0x20'u8, 0x00'u8, 0x28'u8, 0x00'u8, 0x30'u8, 0x05'u8, 0x38'u8, 0x01'u8, 0x0A'u8, 0x36'u8, 0x0A'u8, 0x28'u8, 0x0A'u8, 0x24'u8, 0x01'u8, 0x55'u8, 0x12'u8, 0x20'u8, 0x00'u8, 0x01'u8, 0x02'u8, 0x03'u8, 0x04'u8, 0x05'u8, 0x06'u8, 0x07'u8, 0x08'u8, 0x09'u8, 0x0A'u8, 0x0B'u8, 0x0C'u8, 0x0D'u8, 0x0E'u8, 0x0F'u8, 0x10'u8, 0x11'u8, 0x12'u8, 0x13'u8, 0x14'u8, 0x15'u8, 0x16'u8, 0x17'u8, 0x18'u8, 0x19'u8, 0x1A'u8, 0x1B'u8, 0x1C'u8, 0x1D'u8, 0x1E'u8, 0xBB'u8, 0x10'u8, 0x64'u8, 0x10'u8, 0x32'u8, 0x18'u8, 0x01'u8, 0x20'u8, 0x00'u8, 0x28'u8, 0x01'u8, 0x30'u8, 0x0A'u8, 0x38'u8, 0x02'u8, 0x10'u8, 0x01'u8, ] const Expected_presenceDontHave = @[ 0x0A'u8, 0x02'u8, 0x10'u8, 0x00'u8, 0x22'u8, 0x2E'u8, 0x0A'u8, 0x28'u8, 0x0A'u8, 0x24'u8, 0x01'u8, 0x55'u8, 0x12'u8, 0x20'u8, 0x00'u8, 0x01'u8, 0x02'u8, 0x03'u8, 0x04'u8, 0x05'u8, 0x06'u8, 0x07'u8, 0x08'u8, 0x09'u8, 0x0A'u8, 0x0B'u8, 0x0C'u8, 0x0D'u8, 0x0E'u8, 0x0F'u8, 0x10'u8, 0x11'u8, 0x12'u8, 0x13'u8, 0x14'u8, 0x15'u8, 0x16'u8, 0x17'u8, 0x18'u8, 0x19'u8, 0x1A'u8, 0x1B'u8, 0x1C'u8, 0x1D'u8, 0x1E'u8, 0xAA'u8, 0x10'u8, 0x07'u8, 0x10'u8, 0x00'u8, 0x20'u8, 0x64'u8, ] const Expected_presenceHaveRange = @[ 0x0A'u8, 0x02'u8, 0x10'u8, 0x00'u8, 0x22'u8, 0x3B'u8, 0x0A'u8, 0x28'u8, 0x0A'u8, 0x24'u8, 0x01'u8, 0x55'u8, 0x12'u8, 0x20'u8, 0x00'u8, 0x01'u8, 0x02'u8, 0x03'u8, 0x04'u8, 0x05'u8, 0x06'u8, 0x07'u8, 0x08'u8, 0x09'u8, 0x0A'u8, 0x0B'u8, 0x0C'u8, 0x0D'u8, 0x0E'u8, 0x0F'u8, 0x10'u8, 0x11'u8, 0x12'u8, 0x13'u8, 0x14'u8, 0x15'u8, 0x16'u8, 0x17'u8, 0x18'u8, 0x19'u8, 0x1A'u8, 0x1B'u8, 0x1C'u8, 0x1D'u8, 0x1E'u8, 0xBB'u8, 0x10'u8, 0x00'u8, 0x10'u8, 0x01'u8, 0x1A'u8, 0x04'u8, 0x08'u8, 0x00'u8, 0x10'u8, 0x0A'u8, 0x1A'u8, 0x04'u8, 0x08'u8, 0x64'u8, 0x10'u8, 0x32'u8, 0x20'u8, 0xF4'u8, 0x03'u8, ] const Expected_presenceComplete = @[ 0x0A'u8, 0x02'u8, 0x10'u8, 0x00'u8, 0x22'u8, 0x30'u8, 0x0A'u8, 0x29'u8, 0x0A'u8, 0x24'u8, 0x01'u8, 0x55'u8, 0x12'u8, 0x20'u8, 0x00'u8, 0x01'u8, 0x02'u8, 0x03'u8, 0x04'u8, 0x05'u8, 0x06'u8, 0x07'u8, 0x08'u8, 0x09'u8, 0x0A'u8, 0x0B'u8, 0x0C'u8, 0x0D'u8, 0x0E'u8, 0x0F'u8, 0x10'u8, 0x11'u8, 0x12'u8, 0x13'u8, 0x14'u8, 0x15'u8, 0x16'u8, 0x17'u8, 0x18'u8, 0x19'u8, 0x1A'u8, 0x1B'u8, 0x1C'u8, 0x1D'u8, 0x1E'u8, 0xAA'u8, 0x10'u8, 0xE7'u8, 0x07'u8, 0x10'u8, 0x02'u8, 0x20'u8, 0x8F'u8, 0x4E'u8, ] const Expected_fullMessage = @[ 0x0A'u8, 0x3A'u8, 0x0A'u8, 0x36'u8, 0x0A'u8, 0x28'u8, 0x0A'u8, 0x24'u8, 0x01'u8, 0x55'u8, 0x12'u8, 0x20'u8, 0x00'u8, 0x01'u8, 0x02'u8, 0x03'u8, 0x04'u8, 0x05'u8, 0x06'u8, 0x07'u8, 0x08'u8, 0x09'u8, 0x0A'u8, 0x0B'u8, 0x0C'u8, 0x0D'u8, 0x0E'u8, 0x0F'u8, 0x10'u8, 0x11'u8, 0x12'u8, 0x13'u8, 0x14'u8, 0x15'u8, 0x16'u8, 0x17'u8, 0x18'u8, 0x19'u8, 0x1A'u8, 0x1B'u8, 0x1C'u8, 0x1D'u8, 0x1E'u8, 0xAA'u8, 0x10'u8, 0x01'u8, 0x10'u8, 0x05'u8, 0x18'u8, 0x00'u8, 0x20'u8, 0x00'u8, 0x28'u8, 0x00'u8, 0x30'u8, 0x02'u8, 0x38'u8, 0x01'u8, 0x10'u8, 0x00'u8, 0x22'u8, 0x34'u8, 0x0A'u8, 0x28'u8, 0x0A'u8, 0x24'u8, 0x01'u8, 0x55'u8, 0x12'u8, 0x20'u8, 0x00'u8, 0x01'u8, 0x02'u8, 0x03'u8, 0x04'u8, 0x05'u8, 0x06'u8, 0x07'u8, 0x08'u8, 0x09'u8, 0x0A'u8, 0x0B'u8, 0x0C'u8, 0x0D'u8, 0x0E'u8, 0x0F'u8, 0x10'u8, 0x11'u8, 0x12'u8, 0x13'u8, 0x14'u8, 0x15'u8, 0x16'u8, 0x17'u8, 0x18'u8, 0x19'u8, 0x1A'u8, 0x1B'u8, 0x1C'u8, 0x1D'u8, 0x1E'u8, 0xBB'u8, 0x10'u8, 0x0A'u8, 0x10'u8, 0x01'u8, 0x1A'u8, 0x04'u8, 0x08'u8, 0x05'u8, 0x10'u8, 0x03'u8, 0x20'u8, 0x01'u8, 0x22'u8, 0x2E'u8, 0x0A'u8, 0x28'u8, 0x0A'u8, 0x24'u8, 0x01'u8, 0x55'u8, 0x12'u8, 0x20'u8, 0x00'u8, 0x01'u8, 0x02'u8, 0x03'u8, 0x04'u8, 0x05'u8, 0x06'u8, 0x07'u8, 0x08'u8, 0x09'u8, 0x0A'u8, 0x0B'u8, 0x0C'u8, 0x0D'u8, 0x0E'u8, 0x0F'u8, 0x10'u8, 0x11'u8, 0x12'u8, 0x13'u8, 0x14'u8, 0x15'u8, 0x16'u8, 0x17'u8, 0x18'u8, 0x19'u8, 0x1A'u8, 0x1B'u8, 0x1C'u8, 0x1D'u8, 0x1E'u8, 0xAA'u8, 0x10'u8, 0x14'u8, 0x10'u8, 0x02'u8, 0x20'u8, 0x01'u8, ] const Expected_largeVarints = @[ 0x0A'u8, 0x55'u8, 0x0A'u8, 0x51'u8, 0x0A'u8, 0x2D'u8, 0x0A'u8, 0x24'u8, 0x01'u8, 0x55'u8, 0x12'u8, 0x20'u8, 0x00'u8, 0x01'u8, 0x02'u8, 0x03'u8, 0x04'u8, 0x05'u8, 0x06'u8, 0x07'u8, 0x08'u8, 0x09'u8, 0x0A'u8, 0x0B'u8, 0x0C'u8, 0x0D'u8, 0x0E'u8, 0x0F'u8, 0x10'u8, 0x11'u8, 0x12'u8, 0x13'u8, 0x14'u8, 0x15'u8, 0x16'u8, 0x17'u8, 0x18'u8, 0x19'u8, 0x1A'u8, 0x1B'u8, 0x1C'u8, 0x1D'u8, 0x1E'u8, 0xAA'u8, 0x10'u8, 0xFF'u8, 0xFF'u8, 0xFF'u8, 0xFF'u8, 0xFF'u8, 0x1F'u8, 0x10'u8, 0xFF'u8, 0xFF'u8, 0xFF'u8, 0xFF'u8, 0x07'u8, 0x18'u8, 0x00'u8, 0x20'u8, 0x00'u8, 0x28'u8, 0x00'u8, 0x30'u8, 0xEF'u8, 0xFD'u8, 0xB6'u8, 0xF5'u8, 0xED'u8, 0xD7'u8, 0xAE'u8, 0xFF'u8, 0xCA'u8, 0x01'u8, 0x38'u8, 0xFF'u8, 0xFF'u8, 0xFF'u8, 0xFF'u8, 0xFF'u8, 0xFF'u8, 0xFF'u8, 0xFF'u8, 0xFF'u8, 0x01'u8, 0x10'u8, 0x00'u8, ] const Expected_allZeroValues = @[ 0x0A'u8, 0x02'u8, 0x10'u8, 0x00'u8, 0x22'u8, 0x34'u8, 0x0A'u8, 0x28'u8, 0x0A'u8, 0x24'u8, 0x01'u8, 0x55'u8, 0x12'u8, 0x20'u8, 0x00'u8, 0x01'u8, 0x02'u8, 0x03'u8, 0x04'u8, 0x05'u8, 0x06'u8, 0x07'u8, 0x08'u8, 0x09'u8, 0x0A'u8, 0x0B'u8, 0x0C'u8, 0x0D'u8, 0x0E'u8, 0x0F'u8, 0x10'u8, 0x11'u8, 0x12'u8, 0x13'u8, 0x14'u8, 0x15'u8, 0x16'u8, 0x17'u8, 0x18'u8, 0x19'u8, 0x1A'u8, 0x1B'u8, 0x1C'u8, 0x1D'u8, 0x1E'u8, 0xAA'u8, 0x10'u8, 0x00'u8, 0x10'u8, 0x00'u8, 0x1A'u8, 0x04'u8, 0x08'u8, 0x00'u8, 0x10'u8, 0x00'u8, 0x20'u8, 0x00'u8, ] const Expected_wantListFullTrueWithPresences = @[ 0x0A'u8, 0x3A'u8, 0x0A'u8, 0x36'u8, 0x0A'u8, 0x28'u8, 0x0A'u8, 0x24'u8, 0x01'u8, 0x55'u8, 0x12'u8, 0x20'u8, 0x00'u8, 0x01'u8, 0x02'u8, 0x03'u8, 0x04'u8, 0x05'u8, 0x06'u8, 0x07'u8, 0x08'u8, 0x09'u8, 0x0A'u8, 0x0B'u8, 0x0C'u8, 0x0D'u8, 0x0E'u8, 0x0F'u8, 0x10'u8, 0x11'u8, 0x12'u8, 0x13'u8, 0x14'u8, 0x15'u8, 0x16'u8, 0x17'u8, 0x18'u8, 0x19'u8, 0x1A'u8, 0x1B'u8, 0x1C'u8, 0x1D'u8, 0x1E'u8, 0xAA'u8, 0x10'u8, 0x03'u8, 0x10'u8, 0x07'u8, 0x18'u8, 0x00'u8, 0x20'u8, 0x00'u8, 0x28'u8, 0x01'u8, 0x30'u8, 0x04'u8, 0x38'u8, 0x0B'u8, 0x10'u8, 0x01'u8, 0x22'u8, 0x34'u8, 0x0A'u8, 0x28'u8, 0x0A'u8, 0x24'u8, 0x01'u8, 0x55'u8, 0x12'u8, 0x20'u8, 0x00'u8, 0x01'u8, 0x02'u8, 0x03'u8, 0x04'u8, 0x05'u8, 0x06'u8, 0x07'u8, 0x08'u8, 0x09'u8, 0x0A'u8, 0x0B'u8, 0x0C'u8, 0x0D'u8, 0x0E'u8, 0x0F'u8, 0x10'u8, 0x11'u8, 0x12'u8, 0x13'u8, 0x14'u8, 0x15'u8, 0x16'u8, 0x17'u8, 0x18'u8, 0x19'u8, 0x1A'u8, 0x1B'u8, 0x1C'u8, 0x1D'u8, 0x1E'u8, 0xBB'u8, 0x10'u8, 0x04'u8, 0x10'u8, 0x01'u8, 0x1A'u8, 0x04'u8, 0x08'u8, 0x00'u8, 0x10'u8, 0x10'u8, 0x20'u8, 0x0B'u8, ] const Expected_threeBlockPresences = @[ 0x0A'u8, 0x02'u8, 0x10'u8, 0x00'u8, 0x22'u8, 0x34'u8, 0x0A'u8, 0x28'u8, 0x0A'u8, 0x24'u8, 0x01'u8, 0x55'u8, 0x12'u8, 0x20'u8, 0x00'u8, 0x01'u8, 0x02'u8, 0x03'u8, 0x04'u8, 0x05'u8, 0x06'u8, 0x07'u8, 0x08'u8, 0x09'u8, 0x0A'u8, 0x0B'u8, 0x0C'u8, 0x0D'u8, 0x0E'u8, 0x0F'u8, 0x10'u8, 0x11'u8, 0x12'u8, 0x13'u8, 0x14'u8, 0x15'u8, 0x16'u8, 0x17'u8, 0x18'u8, 0x19'u8, 0x1A'u8, 0x1B'u8, 0x1C'u8, 0x1D'u8, 0x1E'u8, 0xAA'u8, 0x10'u8, 0x01'u8, 0x10'u8, 0x01'u8, 0x1A'u8, 0x04'u8, 0x08'u8, 0x00'u8, 0x10'u8, 0x08'u8, 0x20'u8, 0x15'u8, 0x22'u8, 0x2E'u8, 0x0A'u8, 0x28'u8, 0x0A'u8, 0x24'u8, 0x01'u8, 0x55'u8, 0x12'u8, 0x20'u8, 0x00'u8, 0x01'u8, 0x02'u8, 0x03'u8, 0x04'u8, 0x05'u8, 0x06'u8, 0x07'u8, 0x08'u8, 0x09'u8, 0x0A'u8, 0x0B'u8, 0x0C'u8, 0x0D'u8, 0x0E'u8, 0x0F'u8, 0x10'u8, 0x11'u8, 0x12'u8, 0x13'u8, 0x14'u8, 0x15'u8, 0x16'u8, 0x17'u8, 0x18'u8, 0x19'u8, 0x1A'u8, 0x1B'u8, 0x1C'u8, 0x1D'u8, 0x1E'u8, 0xBB'u8, 0x10'u8, 0x02'u8, 0x10'u8, 0x00'u8, 0x20'u8, 0x16'u8, 0x22'u8, 0x2E'u8, 0x0A'u8, 0x28'u8, 0x0A'u8, 0x24'u8, 0x01'u8, 0x55'u8, 0x12'u8, 0x20'u8, 0x00'u8, 0x01'u8, 0x02'u8, 0x03'u8, 0x04'u8, 0x05'u8, 0x06'u8, 0x07'u8, 0x08'u8, 0x09'u8, 0x0A'u8, 0x0B'u8, 0x0C'u8, 0x0D'u8, 0x0E'u8, 0x0F'u8, 0x10'u8, 0x11'u8, 0x12'u8, 0x13'u8, 0x14'u8, 0x15'u8, 0x16'u8, 0x17'u8, 0x18'u8, 0x19'u8, 0x1A'u8, 0x1B'u8, 0x1C'u8, 0x1D'u8, 0x1E'u8, 0xAA'u8, 0x10'u8, 0x03'u8, 0x10'u8, 0x02'u8, 0x20'u8, 0x17'u8, ] const Expected_multipleEntriesCancelTrue = @[ 0x0A'u8, 0x72'u8, 0x0A'u8, 0x36'u8, 0x0A'u8, 0x28'u8, 0x0A'u8, 0x24'u8, 0x01'u8, 0x55'u8, 0x12'u8, 0x20'u8, 0x00'u8, 0x01'u8, 0x02'u8, 0x03'u8, 0x04'u8, 0x05'u8, 0x06'u8, 0x07'u8, 0x08'u8, 0x09'u8, 0x0A'u8, 0x0B'u8, 0x0C'u8, 0x0D'u8, 0x0E'u8, 0x0F'u8, 0x10'u8, 0x11'u8, 0x12'u8, 0x13'u8, 0x14'u8, 0x15'u8, 0x16'u8, 0x17'u8, 0x18'u8, 0x19'u8, 0x1A'u8, 0x1B'u8, 0x1C'u8, 0x1D'u8, 0x1E'u8, 0xAA'u8, 0x10'u8, 0x01'u8, 0x10'u8, 0x01'u8, 0x18'u8, 0x01'u8, 0x20'u8, 0x00'u8, 0x28'u8, 0x00'u8, 0x30'u8, 0x01'u8, 0x38'u8, 0x1F'u8, 0x0A'u8, 0x36'u8, 0x0A'u8, 0x28'u8, 0x0A'u8, 0x24'u8, 0x01'u8, 0x55'u8, 0x12'u8, 0x20'u8, 0x00'u8, 0x01'u8, 0x02'u8, 0x03'u8, 0x04'u8, 0x05'u8, 0x06'u8, 0x07'u8, 0x08'u8, 0x09'u8, 0x0A'u8, 0x0B'u8, 0x0C'u8, 0x0D'u8, 0x0E'u8, 0x0F'u8, 0x10'u8, 0x11'u8, 0x12'u8, 0x13'u8, 0x14'u8, 0x15'u8, 0x16'u8, 0x17'u8, 0x18'u8, 0x19'u8, 0x1A'u8, 0x1B'u8, 0x1C'u8, 0x1D'u8, 0x1E'u8, 0xBB'u8, 0x10'u8, 0x02'u8, 0x10'u8, 0x02'u8, 0x18'u8, 0x01'u8, 0x20'u8, 0x00'u8, 0x28'u8, 0x00'u8, 0x30'u8, 0x01'u8, 0x38'u8, 0x20'u8, 0x10'u8, 0x00'u8, ] const Expected_presenceDownloadIdMax = @[ 0x0A'u8, 0x02'u8, 0x10'u8, 0x00'u8, 0x22'u8, 0x37'u8, 0x0A'u8, 0x28'u8, 0x0A'u8, 0x24'u8, 0x01'u8, 0x55'u8, 0x12'u8, 0x20'u8, 0x00'u8, 0x01'u8, 0x02'u8, 0x03'u8, 0x04'u8, 0x05'u8, 0x06'u8, 0x07'u8, 0x08'u8, 0x09'u8, 0x0A'u8, 0x0B'u8, 0x0C'u8, 0x0D'u8, 0x0E'u8, 0x0F'u8, 0x10'u8, 0x11'u8, 0x12'u8, 0x13'u8, 0x14'u8, 0x15'u8, 0x16'u8, 0x17'u8, 0x18'u8, 0x19'u8, 0x1A'u8, 0x1B'u8, 0x1C'u8, 0x1D'u8, 0x1E'u8, 0xAA'u8, 0x10'u8, 0x01'u8, 0x10'u8, 0x00'u8, 0x20'u8, 0xFF'u8, 0xFF'u8, 0xFF'u8, 0xFF'u8, 0xFF'u8, 0xFF'u8, 0xFF'u8, 0xFF'u8, 0xFF'u8, 0x01'u8, ] const Expected_entryRangeCountMax = @[ 0x0A'u8, 0x43'u8, 0x0A'u8, 0x3F'u8, 0x0A'u8, 0x28'u8, 0x0A'u8, 0x24'u8, 0x01'u8, 0x55'u8, 0x12'u8, 0x20'u8, 0x00'u8, 0x01'u8, 0x02'u8, 0x03'u8, 0x04'u8, 0x05'u8, 0x06'u8, 0x07'u8, 0x08'u8, 0x09'u8, 0x0A'u8, 0x0B'u8, 0x0C'u8, 0x0D'u8, 0x0E'u8, 0x0F'u8, 0x10'u8, 0x11'u8, 0x12'u8, 0x13'u8, 0x14'u8, 0x15'u8, 0x16'u8, 0x17'u8, 0x18'u8, 0x19'u8, 0x1A'u8, 0x1B'u8, 0x1C'u8, 0x1D'u8, 0x1E'u8, 0xAA'u8, 0x10'u8, 0x01'u8, 0x10'u8, 0x01'u8, 0x18'u8, 0x00'u8, 0x20'u8, 0x00'u8, 0x28'u8, 0x00'u8, 0x30'u8, 0xFF'u8, 0xFF'u8, 0xFF'u8, 0xFF'u8, 0xFF'u8, 0xFF'u8, 0xFF'u8, 0xFF'u8, 0xFF'u8, 0x01'u8, 0x38'u8, 0x01'u8, 0x10'u8, 0x00'u8, ] const Expected_rangeStartNearMax = @[ 0x0A'u8, 0x02'u8, 0x10'u8, 0x00'u8, 0x22'u8, 0x3D'u8, 0x0A'u8, 0x28'u8, 0x0A'u8, 0x24'u8, 0x01'u8, 0x55'u8, 0x12'u8, 0x20'u8, 0x00'u8, 0x01'u8, 0x02'u8, 0x03'u8, 0x04'u8, 0x05'u8, 0x06'u8, 0x07'u8, 0x08'u8, 0x09'u8, 0x0A'u8, 0x0B'u8, 0x0C'u8, 0x0D'u8, 0x0E'u8, 0x0F'u8, 0x10'u8, 0x11'u8, 0x12'u8, 0x13'u8, 0x14'u8, 0x15'u8, 0x16'u8, 0x17'u8, 0x18'u8, 0x19'u8, 0x1A'u8, 0x1B'u8, 0x1C'u8, 0x1D'u8, 0x1E'u8, 0xAA'u8, 0x10'u8, 0x00'u8, 0x10'u8, 0x01'u8, 0x1A'u8, 0x0D'u8, 0x08'u8, 0xFE'u8, 0xFF'u8, 0xFF'u8, 0xFF'u8, 0xFF'u8, 0xFF'u8, 0xFF'u8, 0xFF'u8, 0xFF'u8, 0x01'u8, 0x10'u8, 0x01'u8, 0x20'u8, 0x29'u8, ] ## Deterministic Cids for stable byte fixtures. ## CIDv1, raw codec (0x55), sha2-256 (0x12, 0x20) + 32 fixed bytes. proc fixedCid(seed: byte): Cid = var bytes = @[ 0x01.byte, 0x55, 0x12, 0x20, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F, ] bytes[^1] = seed Cid.init(bytes).expect("valid Cid bytes") let cidA = fixedCid(0xAA) let cidB = fixedCid(0xBB) suite "Block exchange Message wire-format contract": test "Should encode an empty Message": let msg = Message() check msg.encode() == Expected_emptyMessage test "Should encode a WantList with no entries": let msg1 = Message(wantList: WantList(entries: @[], full: false)) check msg1.encode() == Expected_wantListEmptyFullFalse let msg2 = Message(wantList: WantList(entries: @[], full: true)) check msg2.encode() == Expected_wantListEmptyFullTrue test "Should encode a WantList containing a single entry": let msg = Message( wantList: WantList( entries: @[ WantListEntry( address: BlockAddress(treeCid: cidA, index: 5), priority: 1, cancel: false, wantType: WantType.WantHave, sendDontHave: true, rangeCount: 0, downloadId: 42, ) ] ) ) check msg.encode() == Expected_wantListSingleEntry test "Should encode a WantList containing multiple entries": let msg = Message( wantList: WantList( entries: @[ WantListEntry( address: BlockAddress(treeCid: cidA, index: 0), priority: 10, cancel: false, wantType: WantType.WantHave, sendDontHave: false, rangeCount: 5, downloadId: 1, ), WantListEntry( address: BlockAddress(treeCid: cidB, index: 100), priority: 50, cancel: true, wantType: WantType.WantHave, sendDontHave: true, rangeCount: 10, downloadId: 2, ), ], full: true, ) ) check msg.encode() == Expected_wantListMultipleFullTrue test "Should encode a BlockPresence with DontHave kind": let msg = Message( blockPresences: @[ BlockPresence( address: BlockAddress(treeCid: cidA, index: 7), kind: BlockPresenceType.DontHave, ranges: @[], downloadId: 100, ) ] ) check msg.encode() == Expected_presenceDontHave test "Should encode a BlockPresence with HaveRange kind and multiple ranges": let msg = Message( blockPresences: @[ BlockPresence( address: BlockAddress(treeCid: cidB, index: 0), kind: BlockPresenceType.HaveRange, ranges: @[ IndexRange(start: 0'u64, count: 10'u64), IndexRange(start: 100'u64, count: 50'u64), ], downloadId: 500, ) ] ) check msg.encode() == Expected_presenceHaveRange test "Should encode a BlockPresence with Complete kind": let msg = Message( blockPresences: @[ BlockPresence( address: BlockAddress(treeCid: cidA, index: 999), kind: BlockPresenceType.Complete, ranges: @[], downloadId: 9999, ) ] ) check msg.encode() == Expected_presenceComplete test "Should encode a Message combining WantList and multiple BlockPresences": let msg = Message( wantList: WantList( entries: @[ WantListEntry( address: BlockAddress(treeCid: cidA, index: 1), priority: 5, cancel: false, wantType: WantType.WantHave, sendDontHave: false, rangeCount: 2, downloadId: 1, ) ], full: false, ), blockPresences: @[ BlockPresence( address: BlockAddress(treeCid: cidB, index: 10), kind: BlockPresenceType.HaveRange, ranges: @[IndexRange(start: 5'u64, count: 3'u64)], downloadId: 1, ), BlockPresence( address: BlockAddress(treeCid: cidA, index: 20), kind: BlockPresenceType.Complete, ranges: @[], downloadId: 1, ), ], ) check msg.encode() == Expected_fullMessage test "Should encode a Message with maximum-width varint values": let msg = Message( wantList: WantList( entries: @[ WantListEntry( address: BlockAddress(treeCid: cidA, index: 0xFFFFFFFFFF'u64), priority: int32(0x7FFFFFFF), cancel: false, wantType: WantType.WantHave, sendDontHave: false, rangeCount: 0xCAFEBABE_DEADBEEF'u64, downloadId: 0xFFFFFFFFFFFFFFFF'u64, ) ] ) ) check msg.encode() == Expected_largeVarints test "Should encode a Message with all-zero default values": let msg = Message( blockPresences: @[ BlockPresence( address: BlockAddress(treeCid: cidA, index: 0), kind: BlockPresenceType.DontHave, ranges: @[IndexRange(start: 0'u64, count: 0'u64)], downloadId: 0, ) ] ) check msg.encode() == Expected_allZeroValues test "Should round-trip every captured byte fixture (decode + re-encode)": let fixtures = @[ ("emptyMessage", Expected_emptyMessage), ("wantListEmptyFullFalse", Expected_wantListEmptyFullFalse), ("wantListEmptyFullTrue", Expected_wantListEmptyFullTrue), ("wantListSingleEntry", Expected_wantListSingleEntry), ("wantListMultipleFullTrue", Expected_wantListMultipleFullTrue), ("presenceDontHave", Expected_presenceDontHave), ("presenceHaveRange", Expected_presenceHaveRange), ("presenceComplete", Expected_presenceComplete), ("fullMessage", Expected_fullMessage), ("largeVarints", Expected_largeVarints), ("allZeroValues", Expected_allZeroValues), ("wantListFullTrueWithPresences", Expected_wantListFullTrueWithPresences), ("threeBlockPresences", Expected_threeBlockPresences), ("multipleEntriesCancelTrue", Expected_multipleEntriesCancelTrue), ("presenceDownloadIdMax", Expected_presenceDownloadIdMax), ("entryRangeCountMax", Expected_entryRangeCountMax), ("rangeStartNearMax", Expected_rangeStartNearMax), ] for (name, expected) in fixtures: checkpoint("fixture: " & name) let decoded = Message.decode(expected) check decoded.isOk check decoded.get.encode() == expected test "Should encode a WantList combined with BlockPresences": let msg = Message( wantList: WantList( entries: @[ WantListEntry( address: BlockAddress(treeCid: cidA, index: 3), priority: 7, cancel: false, wantType: WantType.WantHave, sendDontHave: true, rangeCount: 4, downloadId: 11, ) ], full: true, ), blockPresences: @[ BlockPresence( address: BlockAddress(treeCid: cidB, index: 4), kind: BlockPresenceType.HaveRange, ranges: @[IndexRange(start: 0'u64, count: 16'u64)], downloadId: 11, ) ], ) check msg.encode() == Expected_wantListFullTrueWithPresences test "Should encode a Message containing three BlockPresences": let msg = Message( blockPresences: @[ BlockPresence( address: BlockAddress(treeCid: cidA, index: 1), kind: BlockPresenceType.HaveRange, ranges: @[IndexRange(start: 0'u64, count: 8'u64)], downloadId: 21, ), BlockPresence( address: BlockAddress(treeCid: cidB, index: 2), kind: BlockPresenceType.DontHave, ranges: @[], downloadId: 22, ), BlockPresence( address: BlockAddress(treeCid: cidA, index: 3), kind: BlockPresenceType.Complete, ranges: @[], downloadId: 23, ), ] ) check msg.encode() == Expected_threeBlockPresences test "Should encode a WantList where multiple entries have cancel=true": let msg = Message( wantList: WantList( entries: @[ WantListEntry( address: BlockAddress(treeCid: cidA, index: 1), priority: 1, cancel: true, wantType: WantType.WantHave, sendDontHave: false, rangeCount: 1, downloadId: 31, ), WantListEntry( address: BlockAddress(treeCid: cidB, index: 2), priority: 2, cancel: true, wantType: WantType.WantHave, sendDontHave: false, rangeCount: 1, downloadId: 32, ), ], full: false, ) ) check msg.encode() == Expected_multipleEntriesCancelTrue test "Should encode a BlockPresence with downloadId at uint64 maximum": let msg = Message( blockPresences: @[ BlockPresence( address: BlockAddress(treeCid: cidA, index: 1), kind: BlockPresenceType.DontHave, ranges: @[], downloadId: 0xFFFFFFFFFFFFFFFF'u64, ) ] ) check msg.encode() == Expected_presenceDownloadIdMax test "Should encode a WantListEntry with rangeCount at uint64 maximum": let msg = Message( wantList: WantList( entries: @[ WantListEntry( address: BlockAddress(treeCid: cidA, index: 1), priority: 1, cancel: false, wantType: WantType.WantHave, sendDontHave: false, rangeCount: 0xFFFFFFFFFFFFFFFF'u64, downloadId: 1, ) ] ) ) check msg.encode() == Expected_entryRangeCountMax test "Should encode a IndexRange with start near uint64 maximum and count=1": let msg = Message( blockPresences: @[ BlockPresence( address: BlockAddress(treeCid: cidA, index: 0), kind: BlockPresenceType.HaveRange, ranges: @[IndexRange(start: 0xFFFFFFFFFFFFFFFE'u64, count: 1'u64)], downloadId: 41, ) ] ) check msg.encode() == Expected_rangeStartNearMax suite "Block exchange Message decode error handling": test "Should reject empty bytes": let decoded = Message.decode(@[]) check decoded.isErr test "Should reject random garbage bytes": let garbage = @[ 0xFF.byte, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, ] let decoded = Message.decode(garbage) check decoded.isErr test "Should reject truncated bytes": let truncated = Expected_fullMessage[0 ..< 8] let decoded = Message.decode(@truncated) check decoded.isErr test "Should reject bytes with a length-prefix exceeding buffer": # Tag 0x0A = field 1, length-delimited. Length 0xFF claims 255 bytes but # only 2 follow. let malformed = @[0x0A.byte, 0xFF, 0x00, 0x00] let decoded = Message.decode(malformed) check decoded.isErr test "Should reject bytes with an unknown wire type": # Tag 0x0F = field 1, wire type 7 (reserved/invalid). let malformed = @[0x0F.byte, 0x00] let decoded = Message.decode(malformed) check decoded.isErr test "Should not crash on a varint with continuation bits set indefinitely": # 10 bytes with continuation bit set — exceeds varint max length. let malformed = @[0x08.byte, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF] let decoded = Message.decode(malformed) check decoded.isErr test "Should reject a Message containing an invalid Cid": var corrupted = @Expected_presenceDontHave for i in 10 .. 45: corrupted[i] = 0xCC let decoded = Message.decode(corrupted) check decoded.isErr # ============================================================================ # For reference: minprotobuf encoders that produced the Expected_* bytes above. # Kept as documentation of the wire-format derivation. # ============================================================================ when false: import pkg/libp2p/protobuf/minprotobuf proc write*(pb: var ProtoBuffer, field: int, value: BlockAddress) = var ipb = initProtoBuffer() ipb.write(1, value.treeCid.data.buffer) ipb.write(2, value.index.uint64) ipb.finish() pb.write(field, ipb) proc write*(pb: var ProtoBuffer, field: int, value: WantListEntry) = var ipb = initProtoBuffer() ipb.write(1, value.address) ipb.write(2, value.priority.uint64) ipb.write(3, value.cancel.uint) ipb.write(4, value.wantType.uint) ipb.write(5, value.sendDontHave.uint) ipb.write(6, value.rangeCount) ipb.write(7, value.downloadId) ipb.finish() pb.write(field, ipb) proc write*(pb: var ProtoBuffer, field: int, value: WantList) = var ipb = initProtoBuffer() for v in value.entries: ipb.write(1, v) ipb.write(2, value.full.uint) ipb.finish() pb.write(field, ipb) proc write*(pb: var ProtoBuffer, field: int, value: BlockPresence) = var ipb = initProtoBuffer() ipb.write(1, value.address) ipb.write(2, value.kind.uint) for r in value.ranges: var rangePb = initProtoBuffer() rangePb.write(1, r.start) rangePb.write(2, r.count) rangePb.finish() ipb.write(3, rangePb) ipb.write(4, value.downloadId) ipb.finish() pb.write(field, ipb) proc protobufEncode*(value: Message): seq[byte] = var ipb = initProtoBuffer() ipb.write(1, value.wantList) for v in value.blockPresences: ipb.write(4, v) ipb.finish() ipb.buffer