示例#1
0
uint32_t CBTransactionInputDeserialise(CBTransactionInput * self){
	CBByteArray * bytes = CBGetMessage(self)->bytes;
	if (! bytes) {
		CBLogError("Attempting to deserialise a CBTransactionInput with no bytes.");
		return 0;
	}
	if (bytes->length < 41) {
		CBLogError("Attempting to deserialise a CBTransactionInput with less than 41 bytes.");
		return 0;
	}
	CBVarInt scriptLen = CBVarIntDecode(bytes, 36);
	if (scriptLen.val > 10000) {
		CBLogError("Attempting to deserialise a CBTransactionInput with too big a script.");
		return 0;
	}
	uint32_t reqLen = (uint32_t)(40 + scriptLen.size + scriptLen.val);
	if (bytes->length < reqLen) {
		CBLogError("Attempting to deserialise a CBTransactionInput with less bytes than needed according to the length for the script. %i < %i", bytes->length, reqLen);
		return 0;
	}
	// Deserialise by subreferencing byte arrays and reading integers.
	self->prevOut.hash = CBByteArraySubReference(bytes, 0, 32);
	self->prevOut.index = CBByteArrayReadInt32(bytes, 32);
	self->scriptObject = CBNewScriptFromReference(bytes, 36 + scriptLen.size, (uint32_t) scriptLen.val);
	self->sequence = CBByteArrayReadInt32(bytes, (uint32_t) (36 + scriptLen.size + scriptLen.val));
	return reqLen;
}
示例#2
0
uint8_t CBNetworkAddressDeserialise(CBNetworkAddress * self, bool timestamp){
	CBByteArray * bytes = CBGetMessage(self)->bytes;
	if (! bytes) {
		CBLogError("Attempting to deserialise a CBNetworkAddress with no bytes.");
		return 0;
	}
	if (bytes->length < 26 + timestamp * 4) {
		CBLogError("Attempting to deserialise a CBNetworkAddress with less bytes than required.");
		return 0;
	}
	uint8_t start;
	uint64_t twoHoursAgo = time(NULL) - 3600;
	if (timestamp) {
		// Make sure we do not set self->lastSeen later than one hour ago.
		self->lastSeen = CBByteArrayReadInt32(bytes, 0);
		if (self->lastSeen > twoHoursAgo)
			self->lastSeen = twoHoursAgo;
		start = 4;
	}else{
		self->lastSeen = twoHoursAgo;
		start = 0;
	}
	self->services = (CBVersionServices) CBByteArrayReadInt64(bytes, start);
	self->ip = CBNewByteArraySubReference(bytes, start + 8, 16);
	// Determine IP type
	self->type = CBGetIPType(CBByteArrayGetData(self->ip));
	self->port = CBByteArrayReadPort(bytes, start + 24);
	return start + 26;
}
示例#3
0
uint32_t CBTransactionInputDeserialise(CBTransactionInput * self){
	CBByteArray * bytes = CBGetMessage(self)->bytes;
	if (NOT bytes) {
		CBGetMessage(self)->onErrorReceived(CB_ERROR_MESSAGE_DESERIALISATION_NULL_BYTES,"Attempting to deserialise a CBTransactionInput with no bytes.");
		return 0;
	}
	if (bytes->length < 41) {
		CBGetMessage(self)->onErrorReceived(CB_ERROR_MESSAGE_DESERIALISATION_BAD_BYTES,"Attempting to deserialise a CBTransactionInput with less than 41 bytes.");
		return 0;
	}
	CBVarInt scriptLen = CBVarIntDecode(bytes, 36);
	if (scriptLen.val > 10000) {
		CBGetMessage(self)->onErrorReceived(CB_ERROR_MESSAGE_DESERIALISATION_BAD_BYTES,"Attempting to deserialise a CBTransactionInput with too big a script.");
		return 0;
	}
	uint32_t reqLen = (uint32_t)(40 + scriptLen.size + scriptLen.val);
	if (bytes->length < reqLen) {
		CBGetMessage(self)->onErrorReceived(CB_ERROR_MESSAGE_DESERIALISATION_BAD_BYTES,"Attempting to deserialise a CBTransactionInput with less bytes than needed according to the length for the script. %i < %i",bytes->length, reqLen);
		return 0;
	}
	// Deserialise by subreferencing byte arrays and reading integers.
	self->prevOut.hash = CBByteArraySubReference(bytes, 0, 32);
	if (NOT self->prevOut.hash){
		CBGetMessage(self)->onErrorReceived(CB_ERROR_INIT_FAIL,"Cannot create a new CBByteArray in CBTransactionInputDeserialise");
		return 0;
	}
	self->prevOut.index = CBByteArrayReadInt32(bytes, 32);
	self->scriptObject = CBNewScriptFromReference(bytes,36 + scriptLen.size, (uint32_t) scriptLen.val);
	if (NOT self->scriptObject) {
		CBGetMessage(self)->onErrorReceived(CB_ERROR_INIT_FAIL,"Cannot create a new CBScript in CBTransactionInputDeserialise");
		CBReleaseObject(self->prevOut.hash);
		return 0;
	}
	self->sequence = CBByteArrayReadInt32(bytes, (uint32_t) (36 + scriptLen.size + scriptLen.val));
	return reqLen;
}
示例#4
0
uint32_t CBInventoryItemDeserialise(CBInventoryItem * self){
	CBByteArray * bytes = CBGetMessage(self)->bytes;
	if (NOT bytes) {
		CBGetMessage(self)->logError("Attempting to deserialise a CBInventoryItem with no bytes.");
		return 0;
	}
	if (bytes->length < 36) {
		CBGetMessage(self)->logError("Attempting to deserialise a CBInventoryItem with less than 36 bytes.");
		return 0;
	}
	self->type = CBByteArrayReadInt32(bytes, 0);
	self->hash = CBByteArraySubReference(bytes, 4, 32);
	if (NOT self->hash)
		return 0;
	return 36;
}
示例#5
0
uint32_t CBTransactionDeserialise(CBTransaction * self){
	CBByteArray * bytes = CBGetMessage(self)->bytes;
	if (NOT bytes) {
		CBLogError("Attempting to deserialise a CBTransaction with no bytes.");
		return 0;
	}
	if (bytes->length < 10) {
		CBLogError("Attempting to deserialise a CBTransaction with less than 10 bytes.");
		return 0;
	}
	self->version = CBByteArrayReadInt32(bytes, 0);
	CBVarInt inputOutputLen = CBVarIntDecode(bytes, 4);
	if (NOT inputOutputLen.val
		|| inputOutputLen.val * 41 > bytes->length - 10) {
		CBLogError("Attempting to deserialise a CBTransaction with a bad var int for the number of inputs.");
		return 0;
	}
	uint32_t cursor = 4 + inputOutputLen.size;
	self->inputNum = (uint32_t)inputOutputLen.val;
	self->inputs = malloc(sizeof(*self->inputs) * self->inputNum);
	if (NOT self->inputs) {
		CBLogError("Cannot allocate %i bytes of memory in CBTransactionDeserialise for inputs.\n", sizeof(*self->inputs) * self->inputNum);
		return 0;
	}
	for (uint32_t x = 0; x < self->inputNum; x++) {
		CBByteArray * data = CBByteArraySubReference(bytes, cursor, bytes->length-cursor);
		if (NOT data) {
			CBLogError("Cannot create a new CBByteArray in CBTransactionDeserialise for the input number %u.", x);
			return 0;
		}
		CBTransactionInput * input = CBNewTransactionInputFromData(data);
		if (NOT input) {
			CBLogError("Cannot create a new CBTransactionInput in CBTransactionDeserialise for the input number %u.", x);
			CBReleaseObject(data);
			return 0;
		}
		uint32_t len = CBTransactionInputDeserialise(input);
		if (NOT len){
			CBLogError("CBTransaction cannot be deserialised because of an error with the input number %u.", x);
			CBReleaseObject(data);
			return 0;
		}
		// The input was deserialised correctly. Now adjust the length and add it to the transaction.
		data->length = len;
		CBReleaseObject(data);
		self->inputs[x] = input;
		cursor += len; // Move along to next input
	}
	if (bytes->length < cursor + 5) { // Needs at least 5 more for the output CBVarInt and the lockTime
		CBLogError("Attempting to deserialise a CBTransaction with not enough bytes for the outputs and lockTime.");
		return 0;
	}
	inputOutputLen = CBVarIntDecode(bytes, cursor);
	if (NOT inputOutputLen.val
		|| inputOutputLen.val * 9 > bytes->length - 10) {
		CBLogError("Attempting to deserialise a CBTransaction with a bad var int for the number of outputs.");
		return 0;
	}
	cursor += inputOutputLen.size; // Move past output CBVarInt
	self->outputNum = (uint32_t)inputOutputLen.val;
	self->outputs = malloc(sizeof(*self->outputs) * self->outputNum);
	if (NOT self->outputs) {
		CBLogError("Cannot allocate %i bytes of memory in CBTransactionDeserialise for outputs.\n", sizeof(sizeof(*self->outputs) * self->outputNum));
		return 0;
	}
	for (uint32_t x = 0; x < self->outputNum; x++) {
		CBByteArray * data = CBByteArraySubReference(bytes, cursor, bytes->length-cursor);
		if (NOT data) {
			CBLogError("Cannot create a new CBByteArray in CBTransactionDeserialise for the output number %u.", x);
			return 0;
		}
		CBTransactionOutput * output = CBNewTransactionOutputFromData(data);
		if (NOT output) {
			CBLogError("Cannot create a new CBTransactionOutput in CBTransactionDeserialise for the output number %u.", x);
			CBReleaseObject(data);
			return 0;
		}
		uint32_t len = CBTransactionOutputDeserialise(output);
		if (NOT len){
			CBLogError("CBTransaction cannot be deserialised because of an error with the output number %u.", x);
			CBReleaseObject(data);
			return 0;
		}
		// The output was deserialised correctly. Now adjust the length and add it to the transaction.
		data->length = len;
		CBReleaseObject(data);
		self->outputs[x] = output;
		cursor += len; // Move along to next output
	}
	if (bytes->length < cursor + 4) { // Ensure 4 bytes are available for lockTime
		CBLogError("Attempting to deserialise a CBTransaction with not enough bytes for the lockTime.");
		return 0;
	}
	self->lockTime = CBByteArrayReadInt32(bytes, cursor);
	return cursor + 4;
}
示例#6
0
int CBAlertDeserialise(CBAlert * self) {
	
	CBByteArray * bytes = CBGetMessage(self)->bytes;

	if (! bytes) {
		CBLogError("Attempting to deserialise a CBAlert with no bytes.");
		return CB_DESERIALISE_ERROR;
	}
	if (bytes->length < 47) {
		CBLogError("Attempting to deserialise a CBAlert with less than 47 bytes minimally required.");
		return CB_DESERIALISE_ERROR;
	}
	
	CBVarInt payloadLen = CBByteArrayReadVarInt(bytes, 0);
	if (bytes->length < payloadLen.size + payloadLen.val + 1) { // Plus one byte for signature var int. After this check the payload size is used to check the payload contents.
		CBLogError("Attempting to deserialise a CBAlert with less bytes than required for payload.");
		return CB_DESERIALISE_ERROR;
	}
	if (payloadLen.val > 2000) { // Prevent too much memory being used.
		CBLogError("Attempting to deserialise a CBAlert with a payload var int larger than 2000 bytes.");
		return CB_DESERIALISE_ERROR;
	}
	if (payloadLen.val < 45) {
		CBLogError("Attempting to deserialise a CBAlert with a payload var int smaller than 45.");
		return CB_DESERIALISE_ERROR;
	}
	
	int cursor = payloadLen.size;
	
	self->version = CBByteArrayReadInt32(bytes, cursor);
	cursor += 4;
	self->relayUntil = CBByteArrayReadInt64(bytes, cursor);
	cursor += 8;
	self->expiration = CBByteArrayReadInt64(bytes, cursor);
	cursor += 8;
	self->ID = CBByteArrayReadInt32(bytes, cursor);
	cursor += 4;
	self->cancel = CBByteArrayReadInt32(bytes, cursor);
	cursor += 4;
	
	// Add cancel ids
	CBVarInt setCancelLen = CBByteArrayReadVarInt(bytes, cursor);
	if (payloadLen.val < 44 + setCancelLen.size + setCancelLen.val * 4) {
		CBLogError("Attempting to deserialise a CBAlert with a payload var int smaller than required to cover the cancel set.");
		return CB_DESERIALISE_ERROR;
	}
	
	self->setCancelNum = setCancelLen.val;
	cursor += setCancelLen.size;
	
	if (self->setCancelNum) {
		self->setCancel = malloc(sizeof(*self->setCancel) * self->setCancelNum);
		for (int x = 0; x < self->setCancelNum; x++) {
			CBByteArrayReadInt32(bytes, cursor);
			cursor += 4;
		}
	}
	
	self->minVer = CBByteArrayReadInt32(bytes, cursor);
	cursor += 4;
	self->maxVer = CBByteArrayReadInt32(bytes, cursor);
	cursor += 4;
	
	// User Agent strings
	CBVarInt userAgentsLen = CBByteArrayReadVarInt(bytes, cursor);
	if (payloadLen.val < 7 + cursor + userAgentsLen.size + userAgentsLen.val - payloadLen.size) { // 7 for priority and 3 strings
		CBLogError("Attempting to deserialise a CBAlert with a payload var int smaller than required to cover the cancel set and the user agent set assuming empty strings.");
		return CB_DESERIALISE_ERROR;
	}
	
	self->userAgentNum = userAgentsLen.val;
	cursor += userAgentsLen.size;
	
	if (self->userAgentNum) {
		
		self->userAgents = malloc(sizeof(*self->userAgents) * self->userAgentNum);
		
		for (int x = 0; x < self->userAgentNum; x++) {
			// Add each user agent checking each time for space in the payload.
			// No need to check space as there is enough data afterwards for safety.
			CBVarInt userAgentLen = CBByteArrayReadVarInt(bytes, cursor);
			cursor += userAgentLen.size;
			
			if (payloadLen.val < 7 + cursor + userAgentLen.val + self->userAgentNum - x - payloadLen.size) { // 7 for priority and 3 strings. The current user agent size and the rest as if empty strings.
				CBLogError("Attempting to deserialise a CBAlert with a payload var int smaller than required to cover the cancel set and the user agent set up to user agent %" PRIu16 ".", x);
				return CB_DESERIALISE_ERROR;
			}
			
			// Enough space so set user agent
			if (userAgentLen.val){
				self->userAgents[x] = CBNewByteArraySubReference(bytes, cursor, (int)userAgentLen.val);
				CBByteArraySanitise(self->userAgents[x]);
			}else
				self->userAgents[x] = NULL;
			
			cursor += userAgentLen.val;
		}
		
	}
	
	self->priority = CBByteArrayReadInt32(bytes, cursor);
	cursor += 4;
	
	// Strings. Make sure to check the first byte in the var ints to ensure enough space
	int size = CBByteArrayReadVarIntSize(bytes, cursor);
	
	if (payloadLen.val < cursor + size + 2u - payloadLen.size) {
		CBLogError("Attempting to deserialise a CBAlert with a payload var int smaller than required to cover the hidden string var int.");
		return CB_DESERIALISE_ERROR;
	}
		
	CBVarInt hiddenCommentLen = CBByteArrayReadVarInt(bytes, cursor);
	cursor += size;
	
	if (payloadLen.val < cursor + hiddenCommentLen.val + 2 - payloadLen.size) {
		CBLogError("Attempting to deserialise a CBAlert with a payload var int smaller than required to cover the hidden string.");
		return CB_DESERIALISE_ERROR;
	}
		
	self->hiddenComment = hiddenCommentLen.val ? CBNewByteArraySubReference(bytes, cursor, (int)hiddenCommentLen.val) : NULL;
	cursor += hiddenCommentLen.val;
	
	// Displayed string.
	size = CBByteArrayReadVarIntSize(bytes, cursor);
	
	if (payloadLen.val >= cursor + size + 1u - payloadLen.size) {
		
		CBVarInt displayedCommentLen = CBByteArrayReadVarInt(bytes, cursor);
		cursor += size;
		
		if (payloadLen.val >= cursor + displayedCommentLen.val + 1 - payloadLen.size) {
			
			self->displayedComment = displayedCommentLen.val ? CBNewByteArraySubReference(bytes, cursor, (int)displayedCommentLen.val) : NULL;
			cursor += displayedCommentLen.val;
			
			// Reserved string
			size = CBByteArrayReadVarIntSize(bytes, cursor);
			
			if (payloadLen.val >= cursor + size - payloadLen.size) {
				
				CBVarInt reservedLen = CBByteArrayReadVarInt(bytes, cursor);
				cursor += size;
				
				if (payloadLen.val == cursor + reservedLen.val - payloadLen.size) {
					
					self->reserved = reservedLen.val ? CBNewByteArraySubReference(bytes, cursor, (int)reservedLen.val) : NULL;
					cursor += reservedLen.val;
					
					// Finally do signature
					size  = CBByteArrayReadVarIntSize(bytes, cursor);
					
					if (bytes->length >= cursor + size) {
						
						CBVarInt sigLen = CBByteArrayReadVarInt(bytes, cursor);
						cursor += size;
						
						if (bytes->length >= cursor + sigLen.val){
							
							self->payload = CBNewByteArraySubReference(bytes, payloadLen.size, (int)payloadLen.val);
							self->signature = CBNewByteArraySubReference(bytes, cursor, (int)sigLen.val);
							
							// Done signature OK. Now return successfully.
							return cursor += sigLen.val;
							
						}else
							CBLogError("Attempting to deserialise a CBAlert with a byte array length smaller than required to cover the signature.");
						
					}else
						CBLogError("Attempting to deserialise a CBAlert with a byte array length smaller than required to cover the signature var int.");
					
					// Did not pass signature. Release third string.
					if (self->reserved) CBReleaseObject(self->reserved);
					
				}else
					CBLogError("Attempting to deserialise a CBAlert with a payload var int smaller than required to cover the reserved string.");

			}else
				CBLogError("Attempting to deserialise a CBAlert with a payload var int smaller than required to cover the reserved string var int.");

			// Did not pass third string. Release second.
			if (self->displayedComment) CBReleaseObject(self->displayedComment);
			
		}else
			CBLogError("Attempting to deserialise a CBAlert with a payload var int smaller than required to cover the displayed string. %" PRIu64 " < %" PRIu64, payloadLen.val, cursor + displayedCommentLen.val + 1);
		
	}else
		CBLogError("Attempting to deserialise a CBAlert with a payload var int smaller than required to cover the displayed string var int.");
	
	// Did not pass second string. Release first.
	if (self->hiddenComment) CBReleaseObject(self->hiddenComment);
	
	// Error
	return CB_DESERIALISE_ERROR;
}
示例#7
0
uint32_t CBVersionDeserialise(CBVersion * self){
	CBByteArray * bytes = CBGetMessage(self)->bytes;
	if (NOT bytes) {
		CBGetMessage(self)->logError("Attempting to deserialise a CBVersion with no bytes.");
		return 0;
	}
	if (bytes->length < 46) {
		CBGetMessage(self)->logError("Attempting to deserialise a CBVersion with less than 46 bytes.");
		return 0;
	}
	self->version = CBByteArrayReadInt32(bytes, 0);
	self->services = (CBVersionServices) CBByteArrayReadInt64(bytes, 4);
	self->time = CBByteArrayReadInt64(bytes, 12);
	CBByteArray * data = CBByteArraySubReference(bytes, 20, bytes->length-20); // Get data from 20 bytes to the end of the byte array to deserialise the recieving network address.
	if (NOT data) {
		CBGetMessage(self)->logError("Cannot create a new CBByteArray in CBVersionDeserialise for the receiving address.");
		return 0;
	}
	self->addRecv = CBNewNetworkAddressFromData(data, CBGetMessage(self)->logError);
	if (NOT self->addRecv) {
		CBGetMessage(self)->logError("Cannot create a new CBNetworkAddress in CBVersionDeserialise for the receiving address.");
		CBReleaseObject(data);
		return 0;
	}
	uint32_t len = CBNetworkAddressDeserialise(self->addRecv, false); // No time from version message.
	if (NOT len){
		CBGetMessage(self)->logError("CBVersion cannot be deserialised because of an error with the receiving address.");
		CBReleaseObject(data);
		return 0;
	}
	// Readjust CBByteArray length for recieving address
	data->length = len;
	CBReleaseObject(data);
	if (self->version >= 106) { // ??? Very old. No need for backwards compatibility? Might as well.
		if (bytes->length < 85) {
			CBGetMessage(self)->logError("Attempting to deserialise a CBVersion with less than 85 bytes required.");
			return 0;
		}
		// Source address deserialisation
		data = CBByteArraySubReference(bytes, 46, bytes->length-46);
		if (NOT data) {
			CBGetMessage(self)->logError("Cannot create a new CBByteArray in CBVersionDeserialise for the source address.");
			return 0;
		}
		self->addSource = CBNewNetworkAddressFromData(data, CBGetMessage(self)->logError);
		if (NOT self->addSource) {
			CBGetMessage(self)->logError("Cannot create a new CBNetworkAddress in CBVersionDeserialise for the source address.");
			CBReleaseObject(data);
			return 0;
		}
		uint32_t len = CBNetworkAddressDeserialise(self->addSource, false); // No time from version message.
		if (NOT len){
			CBGetMessage(self)->logError("CBVersion cannot be deserialised because of an error with the source address.");
			CBReleaseObject(data);
			return 0;
		}
		// Readjust CBByteArray length for source address
		data->length = len;
		CBReleaseObject(data);
		self->nonce = CBByteArrayReadInt64(bytes, 72);
		uint8_t x = CBByteArrayGetByte(bytes, 80); // Check length for decoding CBVarInt
		if (x > 253){
			CBGetMessage(self)->logError("Attempting to deserialise a CBVersion with a var string that is too big.");
			return 0;
		}
		CBVarInt varInt = CBVarIntDecode(bytes, 80);
		if (bytes->length < 84 + varInt.size + varInt.val) {
			CBGetMessage(self)->logError("Attempting to deserialise a CBVersion without enough space to cover the userAgent and block height.");
			return 0;
		}
		if (varInt.val > 400) { // cbitcoin accepts userAgents upto 400 bytes
			CBGetMessage(self)->logError("Attempting to deserialise a CBVersion with a userAgent over 400 bytes.");
			return 0;
		}
		self->userAgent = CBNewByteArraySubReference(bytes, 80 + varInt.size, (uint32_t)varInt.val);
		if (NOT self->userAgent) {
			CBGetMessage(self)->logError("Cannot create a new CBByteArray in CBVersionDeserialise");
			return 0;
		}
		self->blockHeight = CBByteArrayReadInt32(bytes, 80 + varInt.size + (uint32_t)varInt.val);
		return 84 + varInt.size + (uint32_t)varInt.val;
	}else return 46; // Not the further message.
}
示例#8
0
uint32_t CBBlockDeserialise(CBBlock * self, bool transactions){
	CBByteArray * bytes = CBGetMessage(self)->bytes;
	if (NOT bytes) {
		CBLogError("Attempting to deserialise a CBBlock with no bytes.");
		return 0;
	}
	if (bytes->length < 82) {
		CBLogError("Attempting to deserialise a CBBlock with less than 82 bytes. Minimum for header (With null byte).");
		return 0;
	}
	self->version = CBByteArrayReadInt32(bytes, 0);
	self->prevBlockHash = CBByteArraySubReference(bytes, 4, 32);
	if (NOT self->prevBlockHash){
		CBLogError("Cannot create the previous block hash CBByteArray in CBBlockDeserialise.");
		return 0;
	}
	self->merkleRoot = CBByteArraySubReference(bytes, 36, 32);
	if (NOT self->merkleRoot){
		CBLogError("Cannot create the merkle root CBByteArray in CBBlockDeserialise.");
		return 0;
	}
	self->time = CBByteArrayReadInt32(bytes, 68);
	self->target = CBByteArrayReadInt32(bytes, 72);
	self->nonce = CBByteArrayReadInt32(bytes, 76);
	// If first VarInt byte is zero, then stop here for headers, otherwise look for 8 more bytes and continue
	uint8_t firstByte = CBByteArrayGetByte(bytes, 80);
	if (transactions && firstByte) {
		// More to come
		if (bytes->length < 89) {
			CBLogError("Attempting to deserialise a CBBlock with a non-zero varint with less than 89 bytes.");
			return 0;
		}
		CBVarInt transactionNumVarInt = CBVarIntDecode(bytes, 80);
		if (transactionNumVarInt.val*60 > bytes->length - 81) {
			CBLogError("Attempting to deserialise a CBBlock with too many transactions for the byte data length.");
			return 0;
		}
		self->transactionNum = (uint32_t)transactionNumVarInt.val;
		self->transactions = malloc(sizeof(*self->transactions) * self->transactionNum);
		if (NOT self->transactionNum) {
			CBLogError("Cannot allocate %i bytes of memory in CBBlockDeserialise\n", sizeof(*self->transactions) * self->transactionNum);
			return 0;
		}
		uint32_t cursor = 80 + transactionNumVarInt.size;
		for (uint16_t x = 0; x < self->transactionNum; x++) {
			CBByteArray * data = CBByteArraySubReference(bytes, cursor, bytes->length-cursor);
			if (NOT data) {
				CBLogError("Could not create a new CBByteArray in CBBlockDeserialise for the transaction number %u.", x);
			}
			CBTransaction * transaction = CBNewTransactionFromData(data);
			if (NOT transaction){
				CBLogError("Could not create a new CBTransaction in CBBlockDeserialise for the transaction number %u.", x);
				CBReleaseObject(data);
				return 0;
			}
			uint32_t len = CBTransactionDeserialise(transaction);
			if (NOT len){
				CBLogError("CBBlock cannot be deserialised because of an error with the transaction number %u.", x);
				CBReleaseObject(data);
				return 0;
			}
			// Read just the CBByteArray length
			data->length = len;
			CBReleaseObject(data);
			self->transactions[x] = transaction;
			cursor += len;
		}
		return cursor;
	}else{ // Just header
		uint8_t x;
		if (firstByte < 253) {
			x = 1;
		}else if (firstByte == 253){
			x = 2;
		}else if (firstByte == 254){
			x = 4;
		}else{
			x = 8;
		}
		if (bytes->length < 80 + x + 1) {
			CBLogError("Attempting to deserialise a CBBlock header with not enough space to cover the var int.");
			return 0;
		}
		self->transactionNum = (uint32_t)CBVarIntDecode(bytes, 80).val; // This value is undefined in the protocol. Should best be zero when getting the headers since there is not supposed to be any transactions. Would have probably been better if the var int was dropped completely for headers only.
		// Ensure null byte is null. This null byte is a bit of a nuissance but it exists in the protocol when there are no transactions.
		if (CBByteArrayGetByte(bytes, 80 + x) != 0) {
			CBLogError("Attempting to deserialise a CBBlock header with a final byte which is not null. This is not what it is supposed to be but you already knew that right?");
			return 0;
		}
		return 80 + x + 1; // 80 header bytes, the var int and the null byte
	}
}