Exemplo n.º 1
0
bool CBInitNode(CBNode * self, CBDepObject database, CBNodeFlags flags, CBNodeCallbacks nodeCallbacks, CBNetworkCommunicatorCallbacks commCallbacks, CBOnMessageReceivedAction (*onMessageReceived)(CBNode *, CBPeer *, CBMessage *)){
	self->flags = flags;
	self->database = database;
	self->callbacks = nodeCallbacks;
	self->onMessageReceived = onMessageReceived;
	// Initialise network communicator
	CBNetworkCommunicator * comm = CBGetNetworkCommunicator(self);
	commCallbacks.onMessageReceived = CBNodeOnMessageReceived;
	CBInitNetworkCommunicator(comm, CB_SERVICE_FULL_BLOCKS, commCallbacks);
	// Set network communicator fields.
	comm->flags = CB_NETWORK_COMMUNICATOR_AUTO_DISCOVERY | CB_NETWORK_COMMUNICATOR_AUTO_HANDSHAKE | CB_NETWORK_COMMUNICATOR_AUTO_PING;
	if (flags & CB_NODE_BOOTSTRAP)
		comm->flags |= CB_NETWORK_COMMUNICATOR_BOOTSTRAP;
	comm->version = CB_PONG_VERSION;
	comm->networkID = CB_PRODUCTION_NETWORK_BYTES; // ??? Add testnet support
	CBNetworkCommunicatorSetAlternativeMessages(comm, NULL, NULL);
	// Create address manager
	comm->addresses = CBNewNetworkAddressManager(CBNodeOnBadTime);
	comm->addresses->maxAddressesInBucket = 1000;
	comm->addresses->callbackHandler = self;
	// Initialise thread data
	self->shutDownThread = false;
	self->messageQueue = NULL;
	CBNewMutex(&self->blockAndTxMutex);
	CBNewMutex(&self->messageProcessMutex);
	CBNewCondition(&self->messageProcessWaitCond);
	CBNewThread(&self->messageProcessThread, CBNodeProcessMessages, self);
	// Initialise the storage objects
	if (CBNewBlockChainStorage(&self->blockChainStorage, database)) {
		if (CBNewAccounterStorage(&self->accounterStorage, database)){
			if (CBNewNodeStorage(&self->nodeStorage, database)){
				// Setup address storage
				if (CBNewAddressStorage(&comm->addrStorage, database)) {
					if (CBAddressStorageLoadAddresses(comm->addrStorage, comm->addresses)){
						comm->useAddrStorage = true;
						return true;
					}
				}else
					CBLogError("Could not create the address storage object for a node");
				CBFreeNodeStorage(self->nodeStorage);
			}else
				CBLogError("Could not create the node storage object for a node");
			CBFreeAccounterStorage(self->accounterStorage);
		}else
			CBLogError("Could not create the accounter storage object for a node");
		CBFreeBlockChainStorage(self->blockChainStorage);
	}else
		CBLogError("Could not create the block storage object for a node");
	CBDestroyNetworkCommunicator(self);
	return false;
}
Exemplo n.º 2
0
bool BEInitFullNode(BEFullNode * self,void (*onErrorReceived)(CBError error,char *,...)){
	if (NOT CBInitNetworkCommunicator(CBGetNetworkCommunicator(self), onErrorReceived))
		return false;
	// Set network communicator fields.
	CBGetNetworkCommunicator(self)->blockHeight = 0;
	CBGetNetworkCommunicator(self)->callbackHandler = self;
	CBGetNetworkCommunicator(self)->flags = CB_NETWORK_COMMUNICATOR_AUTO_DISCOVERY | CB_NETWORK_COMMUNICATOR_AUTO_HANDSHAKE | CB_NETWORK_COMMUNICATOR_AUTO_PING;
	CBGetNetworkCommunicator(self)->version = CB_PONG_VERSION;
	CBNetworkCommunicatorSetAlternativeMessages(CBGetNetworkCommunicator(self), NULL, NULL);
	// Find home directory.
	const char * homeDir;
	struct passwd * pwd = getpwuid(getuid());
	if (NOT pwd)
		return false;
	homeDir = pwd->pw_dir;
	unsigned long homeLen = strlen(homeDir);
	// Open or create a new address store
	unsigned long dataDirLen = strlen(BE_DATA_DIRECTORY);
	char * addressFilePath = malloc(homeLen + dataDirLen + strlen(BE_ADDRESS_DATA_FILE) + 1);
	memcpy(addressFilePath, homeDir, homeLen);
	memcpy(addressFilePath + homeLen, BE_DATA_DIRECTORY, strlen(BE_DATA_DIRECTORY));
	strcpy(addressFilePath + homeLen + dataDirLen, BE_ADDRESS_DATA_FILE);
	self->addressFile = fopen(addressFilePath, "rb+");
	if (self->addressFile) {
		// The address store exists.
		free(addressFilePath);
		// Get the file length
		fseek(self->addressFile, 0, SEEK_END);
		unsigned long fileLen = ftell(self->addressFile);
		fseek(self->addressFile, 0, SEEK_SET);
		// Read file into a CBByteArray
		CBByteArray * buffer = CBNewByteArrayOfSize((uint32_t)fileLen, onErrorReceived);
		if (NOT buffer) {
			fclose(self->addressFile);
			return false;
		}
		if(fread(CBByteArrayGetData(buffer), fileLen, 1, self->addressFile) != fileLen){
			CBReleaseObject(buffer);
			fclose(self->addressFile);
			return false;
		}
		// Create the CBAddressManager
		CBGetNetworkCommunicator(self)->addresses = CBNewAddressManagerFromData(buffer, onErrorReceived, BEFullNodeOnBadTime);
		CBReleaseObject(buffer);
		if (NOT CBAddressManagerDeserialise(CBGetNetworkCommunicator(self)->addresses)){
			fclose(self->addressFile);
			CBReleaseObject(CBGetNetworkCommunicator(self)->addresses);
			onErrorReceived(CB_ERROR_INIT_FAIL,"There was an error when deserialising the CBAddressManager for the BEFullNode.");
			return false;
		}
	}else{
		// The address store does not exist
		CBGetNetworkCommunicator(self)->addresses = CBNewAddressManager(onErrorReceived, BEFullNodeOnBadTime);
		if (NOT CBGetNetworkCommunicator(self)->addresses)
			return false;
		// Create the file
		self->addressFile = fopen(addressFilePath, "wb");
		free(addressFilePath);
		if (NOT self->addressFile){
			CBReleaseObject(CBGetNetworkCommunicator(self)->addresses);
			return false;
		}
	}
	// Create block validator
	
	return true;
}
Exemplo n.º 3
0
void BEFreeFullNode(void * self){
	fclose(BEGetFullNode(self)->addressFile);
	CBReleaseObject(CBGetNetworkCommunicator(self)->addresses);
	CBFreeNetworkCommunicator(self);
}
Exemplo n.º 4
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;
}
Exemplo n.º 5
0
void CBNodeDisconnectPeer(CBPeer * peer){
	CBRetainObject(peer);
	CBRunOnEventLoop(CBGetNetworkCommunicator(peer->nodeObj)->eventLoop, CBNodeDisconnectPeerRun, peer, false);
}