Пример #1
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;
}
Пример #2
0
uint16_t CBChainDescriptorDeserialise(CBChainDescriptor * self){
	CBByteArray * bytes = CBGetMessage(self)->bytes;
	if (! bytes) {
		CBLogError("Attempting to deserialise a CBChainDescriptor with no bytes.");
		return 0;
	}
	if (bytes->length < 1) {
		CBLogError("Attempting to deserialise a CBChainDescriptor with no bytes");
		return 0;
	}
	CBVarInt hashNum = CBVarIntDecode(bytes, 0);
	if (hashNum.val > 500) {
		CBLogError("Attempting to deserialise a CBChainDescriptor with a var int over 500.");
		return 0;
	}
	if (bytes->length < hashNum.size + hashNum.val * 32) {
		CBLogError("Attempting to deserialise a CBChainDescriptor with less bytes than required for the hashes.");
		return 0;
	}
	// Deserialise each hash
	self->hashes = malloc(sizeof(*self->hashes) * (size_t)hashNum.val);
	self->hashNum = hashNum.val;
	uint16_t cursor = hashNum.size;
	for (uint16_t x = 0; x < self->hashNum; x++) {
		self->hashes[x] = CBNewByteArraySubReference(bytes, cursor, 32);
		cursor += 32;
	}
	return cursor;
}
Пример #3
0
CBByteArray * CBAlertGetPayload(CBAlert * self) {
	
	CBByteArray * bytes = CBGetMessage(self)->bytes;
	CBVarInt payloadLen = CBByteArrayReadVarInt(bytes, 0);
	
	return CBNewByteArraySubReference(bytes, payloadLen.size, (int)payloadLen.val);
	
}
Пример #4
0
bool CBAlertSerialisePayload(CBAlert * self) {
	
	CBByteArray * bytes = CBGetMessage(self)->bytes;
	if (! bytes) {
		CBLogError("Attempting to serialise a CBAlert with no bytes.");
		return false;
	}
	
	// Create varints and calculate length whilst at it.
	CBVarInt setCancelLen = CBVarIntFromUInt64(self->setCancelNum);
	CBVarInt userAgentLen = CBVarIntFromUInt64(self->userAgentNum);
	CBVarInt hiddenCommentLen = CBVarIntFromUInt64(self->hiddenComment ? self->hiddenComment->length : 0);
	CBVarInt displayedCommentLen = CBVarIntFromUInt64(self->displayedComment ? self->displayedComment->length : 0);
	CBVarInt reservedLen = CBVarIntFromUInt64(self->reserved ? self->reserved->length : 0);
	int length = 40 + setCancelLen.size + setCancelLen.val * 4 + userAgentLen.size + hiddenCommentLen.size + hiddenCommentLen.val + displayedCommentLen.size + displayedCommentLen.val + reservedLen.size + reservedLen.val;
	
	// Add user agents to length
	for (int x = 0; x < self->userAgentNum; x++)
		length += self->userAgents[x]->length + CBVarIntSizeOf(self->userAgents[x]->length);
	
	// So far length is for payload so make payload var int.
	CBVarInt payloadLen = CBVarIntFromUInt64(length);
	
	// Add the length of this var int.
	length += payloadLen.size;
	
	// Check length, with at least one byte for signature (could be 0 varint)
	if (bytes->length < length + 1) {
		CBLogError("Attempting to serialise a CBAlert with less bytes than required for the payload and a signature var int.");
		return false;
	}
	
	// Serialise the payload section.
	
	CBByteArraySetVarInt(bytes, 0, payloadLen);
	
	int cursor = payloadLen.size;
	CBByteArraySetInt32(bytes, cursor, self->version);
	cursor += 4;
	CBByteArraySetInt64(bytes, cursor, self->relayUntil);
	cursor += 8;
	CBByteArraySetInt64(bytes, cursor, self->expiration);
	cursor += 8;
	CBByteArraySetInt32(bytes, cursor, self->ID);
	cursor += 4;
	CBByteArraySetInt32(bytes, cursor, self->cancel);
	cursor += 4;
	
	// Cancel set
	CBByteArraySetVarInt(bytes, cursor, setCancelLen);
	cursor += setCancelLen.size;
	for (int x = 0; x < self->setCancelNum; x++) {
		CBByteArraySetInt32(bytes, cursor, self->setCancel[x]);
		cursor += 4;
	}
	
	CBByteArraySetInt32(bytes, cursor, self->minVer);
	cursor += 4;
	CBByteArraySetInt32(bytes, cursor, self->maxVer);
	cursor += 4;
	
	// User agent set
	CBByteArraySetVarInt(bytes, cursor, userAgentLen);
	cursor += userAgentLen.size;
	for (int x = 0; x < self->userAgentNum; x++) {
		CBVarInt aUserAgentLen = CBVarIntFromUInt64(self->userAgents[x]->length);
		CBByteArraySetVarInt(bytes, cursor, aUserAgentLen);
		cursor += aUserAgentLen.size;
		CBByteArrayCopyByteArray(bytes, cursor, self->userAgents[x]);
		CBByteArrayChangeReference(self->userAgents[x], bytes, cursor);
		cursor += aUserAgentLen.val;
	}
	
	CBByteArraySetInt32(bytes, cursor, self->priority);
	cursor += 4;
	
	// Hidden comment
	CBByteArraySetVarInt(bytes, cursor, hiddenCommentLen);
	cursor += hiddenCommentLen.size;
	if (self->hiddenComment) {
		CBByteArrayCopyByteArray(bytes, cursor, self->hiddenComment);
		CBByteArrayChangeReference(self->hiddenComment, bytes, cursor);
		cursor += hiddenCommentLen.val;
	}
	
	// Displayed comment
	CBByteArraySetVarInt(bytes, cursor, displayedCommentLen);
	cursor += displayedCommentLen.size;
	if (self->displayedComment) {
		CBByteArrayCopyByteArray(bytes, cursor, self->displayedComment);
		CBByteArrayChangeReference(self->displayedComment, bytes, cursor);
		cursor += displayedCommentLen.val;
	}
	
	// Reserved
	CBByteArraySetVarInt(bytes, cursor, reservedLen);
	cursor += reservedLen.size;
	if (self->reserved) {
		CBByteArrayCopyByteArray(bytes, cursor, self->reserved);
		CBByteArrayChangeReference(self->reserved, bytes, cursor);
		cursor += reservedLen.val;
	}
	
	self->payload = CBNewByteArraySubReference(bytes, payloadLen.size, cursor - payloadLen.size);
	
	return true;
	
}
Пример #5
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;
}
Пример #6
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.
}