Block

C中可變長度整數的實現

  • November 6, 2018

任何人都可以告訴我如何在 C 中實現這個可變長度整數的概念,它編碼了一個塊中的交易數量?根據這裡的描述,我認為是石灰:

if(value=?)
   uint8_t number_transactions = length;
else if(value=?)
   uint16_t number_transactions = 0xFD+length;
else if(value=?)
   uint32_t number_transactions = 0xFE_length;
else
   uint64_t number_transactions = 0xFF_length;

wherenumber_transactions將是塊上連接的值。但是如何實現呢?這段程式碼和比特幣維基中描述的一樣嗎?

更新

char* varint(unsigned long size) {
 char* number;
 if(size < 252) {
   number = malloc(1);
   number[0] = (uint8_t)size;
 } else if(size>=253 && size<65535) {
   number = malloc(3);
   number[0] = 0xfd;
   memcpy(&number[1], (uint16_t)&size, sizeof(uint16_t));
 } else if(size>=65536 && size<4294967295) {
   number = malloc(5);
   number[0] = 0xfe;
   memcpy(&number[1], (uint32_t)&size, sizeof(uint32_t));
 } else if(size>=4294967296) {
   number = malloc(9);
   number[0] = 0xff;
   memcpy(&number[1], (uint64_t)&size, sizeof(uint64_t));
 }
 return NULL;
}

來自編譯器的消息:

bitcoin_rpc.c: In function ‘varint’:
bitcoin_rpc.c:230:24: warning: cast from pointer to integer of different size [-Wpointer-to-int-cast]
    memcpy(&number[1], (uint16_t)&size, sizeof(uint16_t));
                       ^
bitcoin_rpc.c:230:24: warning: passing argument 2 of ‘memcpy’ makes pointer from integer without a cast [-Wint-conversion]
In file included from bitcoin_rpc.c:4:0:
/usr/include/string.h:42:14: note: expected ‘const void * restrict’ but argument is of type ‘short unsigned int’
extern void *memcpy (void *__restrict __dest, const void *__restrict __src,
             ^~~~~~
bitcoin_rpc.c:234:24: warning: cast from pointer to integer of different size [-Wpointer-to-int-cast]
    memcpy(&number[1], (uint32_t)&size, sizeof(uint32_t));
                       ^
bitcoin_rpc.c:234:24: warning: passing argument 2 of ‘memcpy’ makes pointer from integer without a cast [-Wint-conversion]
In file included from bitcoin_rpc.c:4:0:
/usr/include/string.h:42:14: note: expected ‘const void * restrict’ but argument is of type ‘unsigned int’
extern void *memcpy (void *__restrict __dest, const void *__restrict __src,
             ^~~~~~
bitcoin_rpc.c:238:24: warning: passing argument 2 of ‘memcpy’ makes pointer from integer without a cast [-Wint-conversion]
    memcpy(&number[1], (uint64_t)&size, sizeof(uint64_t));
                       ^
In file included from bitcoin_rpc.c:4:0:
/usr/include/string.h:42:14: note: expected ‘const void * restrict’ but argument is of type ‘long unsigned int’
extern void *memcpy (void *__restrict __dest, const void *__restrict __src,

不,緊湊大小的無符號整數不是 uint(一個字節的基數除外)。它們是序列化的,所以它實際上只是一個字節數組。您只需將要序列化的數字與邊界進行比較,然後從那裡確定前綴字節是什麼。Bitcoin.org 更好地描述了這一點:https ://bitcoin.org/en/developer-reference#compactsize-unsigned-integers 。請注意,您需要了解十六進制數字以及它們在 C 中的工作方式。

這是libblkmaker的實現:

static
char varintEncode(unsigned char *out, uint64_t n) {
   if (n < 0xfd)
   {
       out[0] = n;
       return 1;
   }
   char L;
   if (n <= 0xffff)
   {
       out[0] = '\xfd';
       L = 3;
   }
   else
   if (n <= 0xffffffff)
   {
       out[0] = '\xfe';
       L = 5;
   }
   else
   {
       out[0] = '\xff';
       L = 9;
   }
   for (unsigned char i = 1; i < L; ++i)
       out[i] = (n >> ((i - 1) * 8)) % 256;
   return L;
}

引用自:https://bitcoin.stackexchange.com/questions/58786