Пример #1
0
void CBNodeOnValidatorError(void * vself){
	CBNode * self = vself;
	CBMutexUnlock(CBGetNode(self)->blockAndTxMutex);
	CBLogError("There was a validation error.");
	self->callbacks.onFatalNodeError(self, CB_ERROR_VALIDATION);
	CBReleaseObject(self);
}
Пример #2
0
void CBNodeOnBadTime(void * vself){
	CBNode * self = vself;
	CBMutexUnlock(CBGetNode(self)->blockAndTxMutex);
	CBLogError("The system time is potentially incorrect. It does not match with the network time.");
	self->callbacks.onFatalNodeError(self, CB_ERROR_BAD_TIME);
	CBReleaseObject(self);
}
Пример #3
0
CBPeer * CBNewNodeByTakingNetworkAddress(CBNetworkAddress * addr){
	CBPeer * self = CBGetNode(addr);
	self = realloc(self, sizeof(*self));
	if (NOT self) {
		CBLogError("Cannot reallocate to %i bytes of memory in CBNewNodeByTakingNetworkAddress\n", sizeof(*self));
		return NULL;
	}
	CBGetObject(self)->free = CBFreeNode;
	if(CBInitNodeByTakingNetworkAddress(self))
		return self;
	free(self);
	return NULL;
}
Пример #4
0
CBOnMessageReceivedAction CBNodeOnMessageReceived(CBNetworkCommunicator * comm, CBPeer * peer, CBMessage * message){
	CBNode * self = CBGetNode(comm);
	// Add message to queue
	CBRetainObject(message);
	CBRetainObject(peer);
	CBMutexLock(self->messageProcessMutex);
	if (self->messageQueue == NULL)
		self->messageQueue = self->messageQueueBack = malloc(sizeof(*self->messageQueueBack));
	else{
		self->messageQueueBack->next = malloc(sizeof(*self->messageQueueBack));
		self->messageQueueBack = self->messageQueueBack->next;
	}
	self->messageQueueBack->peer = peer;
	self->messageQueueBack->message = message;
	self->messageQueueBack->next = NULL;
	// Wakeup thread if this is the first in the queue
	if (self->messageQueue == self->messageQueueBack)
		// We have just added a block to the queue when there was not one before so wake-up the processing thread.
		CBConditionSignal(self->messageProcessWaitCond);
	CBMutexUnlock(self->messageProcessMutex);
	return CB_MESSAGE_ACTION_CONTINUE;
}
Пример #5
0
CBOnMessageReceivedAction CBNodeSendBlocksInvOrHeaders(CBNode * self, CBPeer * peer, CBGetBlocks * getBlocks, bool full){
	CBChainDescriptor * chainDesc = getBlocks->chainDescriptor;
	if (chainDesc->hashNum == 0)
		// Why do this?
		return CB_MESSAGE_ACTION_DISCONNECT;
	uint8_t branch;
	uint32_t blockIndex;
	// Go though the chain descriptor until a hash is found that we own
	bool found = false;
	// Lock block mutex for block chain access
	CBMutexLock(self->blockAndTxMutex);
	for (uint16_t x = 0; x < chainDesc->hashNum; x++) {
		CBErrBool exists = CBBlockChainStorageGetBlockLocation(CBGetNode(self)->validator, CBByteArrayGetData(chainDesc->hashes[x]), &branch, &blockIndex);
		if (exists == CB_ERROR) {
			CBMutexUnlock(self->blockAndTxMutex);
			return CBNodeReturnError(self, "Could not look for block with chain descriptor hash.");
		}
		if (exists == CB_TRUE) {
			// We have a block that we own.
			found = true;
			break;
		}
	}
	// Get the chain path for the main chain
	CBChainPath mainChainPath = CBValidatorGetMainChainPath(self->validator);
	CBChainPathPoint intersection;
	if (found){
		// Get the chain path for the block header we have found
		CBChainPath peerChainPath = CBValidatorGetChainPath(self->validator, branch, blockIndex);
		// Determine where the intersection is on the main chain
		intersection = CBValidatorGetChainIntersection(&mainChainPath, &peerChainPath);
	}else{
		// Bad chain?
		CBMutexUnlock(self->blockAndTxMutex);
		return CB_MESSAGE_ACTION_DISCONNECT;
	}
	CBMessage * message;
	// Now provide headers from this intersection up to 2000 blocks or block inventory items up to 500, the last one we have or the stopAtHash.
	for (uint16_t x = 0; x < (full ? 500 : 2000); x++) {
		// Check to see if we reached the last block in the main chain.
		if (intersection.chainPathIndex == 0
			&& intersection.blockIndex == mainChainPath.points[0].blockIndex) {
			if (x == 0){
				// The intersection is at the last block. The peer is up-to-date with us
				peer->upload = false;
				peer->upToDate = true;
				CBMutexUnlock(self->blockAndTxMutex);
				return CB_MESSAGE_ACTION_CONTINUE;
			}
			break;
		}
		// Move to the next block
		if (intersection.blockIndex == mainChainPath.points[intersection.chainPathIndex].blockIndex) {
			// Move to next branch
			intersection.chainPathIndex--;
			intersection.blockIndex = 0;
		}else
			// Move to the next block
			intersection.blockIndex++;
		// Get the hash
		uint8_t hash[32];
		if (! CBBlockChainStorageGetBlockHash(self->validator, mainChainPath.points[intersection.chainPathIndex].branch, intersection.blockIndex, hash)) {
			if (x != 0) CBReleaseObject(message);
			CBMutexUnlock(self->blockAndTxMutex);
			return CBNodeReturnError(self, "Could not obtain a hash for a block.");
		}
		// Check to see if we are at stopAtHash
		if (getBlocks->stopAtHash && memcmp(hash, CBByteArrayGetData(getBlocks->stopAtHash), 32) == 0){
			if (x == 0) {
				CBMutexUnlock(self->blockAndTxMutex);
				return CB_MESSAGE_ACTION_CONTINUE;
			}
			break;
		}
		if (x == 0){
			// Create inventory or block headers object to send to peer.
			if (full) {
				message = CBGetMessage(CBNewInventory());
				message->type = CB_MESSAGE_TYPE_INV;
			}else{
				message = CBGetMessage(CBNewBlockHeaders());
				message->type = CB_MESSAGE_TYPE_HEADERS;
			}
		}
		// Add block header or add inventory item
		if (full) {
			CBByteArray * hashObj = CBNewByteArrayWithDataCopy(hash, 32);
			char blkStr[CB_BLOCK_HASH_STR_SIZE];
			CBByteArrayToString(hashObj, 0, CB_BLOCK_HASH_STR_BYTES, blkStr, true);
			CBInventoryTakeInventoryItem(CBGetInventory(message), CBNewInventoryItem(CB_INVENTORY_ITEM_BLOCK, hashObj));
			CBReleaseObject(hashObj);
		}else
			CBBlockHeadersTakeBlockHeader(CBGetBlockHeaders(message), CBBlockChainStorageGetBlockHeader(self->validator, mainChainPath.points[intersection.chainPathIndex].branch, intersection.blockIndex));
	}
	CBMutexUnlock(self->blockAndTxMutex);
	// Send the message
	CBNodeSendMessageOnNetworkThread(CBGetNetworkCommunicator(self), peer, message, NULL);
	CBReleaseObject(message);
	// We are uploading to the peer
	peer->upload = true;
	return CB_MESSAGE_ACTION_CONTINUE;
}