示例#1
0
void CBBlockHeadersAddBlockHeader(CBBlockHeaders * self, CBBlock * header){
	CBRetainObject(header);
	CBBlockHeadersTakeBlockHeader(self, header);
}
示例#2
0
bool CBBlockHeadersAddBlockHeader(CBBlockHeaders * self,CBBlock * header) {
    CBRetainObject(header);
    return CBBlockHeadersTakeBlockHeader(self,header);
}
示例#3
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;
}