Block
C中可變長度整數的實現
任何人都可以告訴我如何在 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;
where
number_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; }