예제 #1
0
bool CBAddressStorageSaveAddress(uint64_t iself, void * address){
	CBAddressStore * self = (CBAddressStore *)iself;
	CBNetworkAddress * addrObj = address;
	// Create key
	memcpy(CB_ADDRESS_KEY + 1, CBByteArrayGetData(addrObj->ip), 16);
	CBInt16ToArray(CB_ADDRESS_KEY, 17, addrObj->port);
	// Create data
	CBInt64ToArray(CB_DATA_ARRAY, 0, addrObj->lastSeen);
	CBInt64ToArray(CB_DATA_ARRAY, 8, (uint64_t) addrObj->services);
	CBInt32ToArray(CB_DATA_ARRAY, 16, addrObj->penalty);
	// Write data
	if (NOT CBDatabaseWriteValue(CBGetDatabase(self), CB_ADDRESS_KEY, CB_DATA_ARRAY, 20)) {
		CBLogError("Could not write an address to storage.");
		return false;
	}
	// Increase the number of addresses
	CBInt32ToArray(CB_DATA_ARRAY, 0, --self->numAddresses);
	if (NOT CBDatabaseWriteValue(CBGetDatabase(self), CB_ADDR_NUM_KEY, CB_DATA_ARRAY, 4)) {
		CBLogError("Could not write the new number of addresses to storage.");
		return false;
	}
	// Commit changes
	if (NOT CBDatabaseCommit(CBGetDatabase(self))) {
		CBLogError("Could not commit adding a new network address to storage.");
		return false;
	}
	return true;
}
bool CBBlockChainStorageDeleteTransactionRef(void * validator, uint8_t * txHash){
	CBFullValidator * validatorObj = validator;
	CBDatabase * database = (CBDatabase *)validatorObj->storage;
	// Place transaction hash into the key
	memcpy(CB_TRANSACTION_INDEX_KEY + 2, txHash, 32);
	// Read the instance count
	if (NOT CBDatabaseReadValue(database, CB_TRANSACTION_INDEX_KEY, CB_DATA_ARRAY, 22, 0)) {
		CBLogError("Could not read a transaction reference from storage.");
		return false;
	}
	uint32_t txInstanceNum = CB_DATA_ARRAY[CB_TRANSACTION_REF_INSTANCE_COUNT] - 1;
	if (txInstanceNum) {
		// There are still more instances of this transaction. Do not remove the transaction, only make the unspent output number equal to zero and decrement the instance count.
		CB_DATA_ARRAY[CB_TRANSACTION_REF_NUM_UNSPENT_OUTPUTS] = 0;
		CB_DATA_ARRAY[CB_TRANSACTION_REF_INSTANCE_COUNT] = txInstanceNum;
		// Write to storage.
		if (NOT CBDatabaseWriteValue(database, CB_TRANSACTION_INDEX_KEY, CB_DATA_ARRAY, 22)) {
			CBLogError("Could not update a transaction reference for deleting an instance.");
			return false;
		}
	}else{
		// This was the last instance.
		// Remove from storage
		if (NOT CBDatabaseRemoveValue(database, CB_TRANSACTION_INDEX_KEY)) {
			CBLogError("Could not remove a transaction reference from storage.");
			return false;
		}
	}
	return true;
}
bool CBBlockChainStorageSaveTransactionRef(void * validator, uint8_t * txHash, uint8_t branch, uint32_t blockIndex, uint32_t outputPos, uint32_t outputsLen, bool coinbase, uint32_t numOutputs){
	CBFullValidator * validatorObj = validator;
	CBDatabase * database = (CBDatabase *)validatorObj->storage;
	memcpy(CB_TRANSACTION_INDEX_KEY + 2, txHash, 32);
	if (CBDatabaseGetLength(database, CB_TRANSACTION_INDEX_KEY)) {
		// We have the transaction already. Thus obtain the data already in the index.
		if (NOT CBDatabaseReadValue(database, CB_TRANSACTION_INDEX_KEY, CB_DATA_ARRAY, 22, 0)) {
			CBLogError("Could not read a transaction reference from the transaction index.");
			return false;
		}
		// Increase the instance count. We change nothing else as we will use the first instance for all other instances.
		CBInt32ToArray(CB_DATA_ARRAY, CB_TRANSACTION_REF_INSTANCE_COUNT, CBArrayToInt32(CB_DATA_ARRAY, CB_TRANSACTION_REF_INSTANCE_COUNT) + 1);
	}else{
		// This transaction has not yet been seen in the block chain.
		CBInt32ToArray(CB_DATA_ARRAY, CB_TRANSACTION_REF_BLOCK_INDEX, blockIndex);
		CB_DATA_ARRAY[CB_TRANSACTION_REF_BRANCH] = branch;
		CBInt32ToArray(CB_DATA_ARRAY, CB_TRANSACTION_REF_POSITION_OUPTUTS, outputPos);
		CBInt32ToArray(CB_DATA_ARRAY, CB_TRANSACTION_REF_LENGTH_OUTPUTS, outputsLen);
		CB_DATA_ARRAY[CB_TRANSACTION_REF_IS_COINBASE] = coinbase;
		// We start with an instance count of one
		CBInt32ToArray(CB_DATA_ARRAY, CB_TRANSACTION_REF_INSTANCE_COUNT, 1);
	}
	// Always set the number of unspent outputs back to the number of outputs in the transaction
	CBInt32ToArray(CB_DATA_ARRAY, CB_TRANSACTION_REF_NUM_UNSPENT_OUTPUTS, numOutputs);
	// Write to the transaction index.
	if (NOT CBDatabaseWriteValue(database, CB_TRANSACTION_INDEX_KEY, CB_DATA_ARRAY, 22)) {
		CBLogError("Could not write transaction reference to transaction index.");
		return false;
	}
	return true;
}
bool CBBlockChainStorageSaveBranchWork(void * validator, uint8_t branch){
	CBFullValidator * validatorObj = validator;
	CBDatabase * database = (CBDatabase *)validatorObj->storage;
	CB_WORK_KEY[2] = branch;
	if (NOT CBDatabaseWriteValue(database, CB_WORK_KEY, validatorObj->branches[branch].work.data, validatorObj->branches[branch].work.length)) {
		CBLogError("Could not write branch work.");
		return false;
	}
	return true;
}
bool CBBlockChainStorageChangeUnspentOutputsNum(CBDatabase * database, uint8_t * txHash, int8_t change){
	// Place transaction hash into the key
	memcpy(CB_TRANSACTION_INDEX_KEY + 2, txHash, 32);
	// Read the number of unspent outputs to be decremented
	if (NOT CBDatabaseReadValue(database, CB_TRANSACTION_INDEX_KEY, CB_DATA_ARRAY, 18, 0))
		return false;
	CBInt32ToArray(CB_DATA_ARRAY, CB_TRANSACTION_REF_NUM_UNSPENT_OUTPUTS, 
				   CBArrayToInt32(CB_DATA_ARRAY, CB_TRANSACTION_REF_NUM_UNSPENT_OUTPUTS) + change);
	// Now write the new value
	return CBDatabaseWriteValue(database, CB_TRANSACTION_INDEX_KEY, CB_DATA_ARRAY, 18);
}
bool CBBlockChainStorageSaveOrphan(void * validator, void * block, uint8_t orphanNum){
	CBFullValidator * validatorObj = validator;
	CBDatabase * database = (CBDatabase *)validatorObj->storage;
	CBBlock * blockObj = block;
	CB_ORPHAN_KEY[2] = orphanNum;
	if (NOT CBDatabaseWriteValue(database, CB_ORPHAN_KEY, CBByteArrayGetData(CBGetMessage(blockObj)->bytes), CBGetMessage(blockObj)->bytes->length)) {
		CBLogError("Could not write an orphan.");
		return false;
	}
	return true;
}
bool CBBlockChainStorageSaveBasicValidator(void * validator){
	CBFullValidator * validatorObj = validator;
	CBDatabase * database = (CBDatabase *)validatorObj->storage;
	CB_DATA_ARRAY[CB_VALIDATION_FIRST_ORPHAN] = validatorObj->firstOrphan;
	CB_DATA_ARRAY[CB_VALIDATION_NUM_ORPHANS] = validatorObj->numOrphans;
	CB_DATA_ARRAY[CB_VALIDATION_MAIN_BRANCH] = validatorObj->mainBranch;
	CB_DATA_ARRAY[CB_VALIDATION_NUM_BRANCHES] = validatorObj->numBranches;
	if (NOT CBDatabaseWriteValue(database, CB_VALIDATOR_INFO_KEY, CB_DATA_ARRAY, 4)) {
		CBLogError("Could not write the initial basic validation data.");
		return false;
	}
	return true;
}
bool CBBlockChainStorageSaveBranch(void * validator, uint8_t branch){
	CBFullValidator * validatorObj = validator;
	CBDatabase * database = (CBDatabase *)validatorObj->storage;
	CB_BRANCH_KEY[2] = branch;
	// Make data
	CBInt32ToArray(CB_DATA_ARRAY, CB_BRANCH_LAST_RETARGET, validatorObj->branches[branch].lastRetargetTime);
	CBInt32ToArray(CB_DATA_ARRAY, CB_BRANCH_LAST_VALIDATION, validatorObj->branches[branch].lastValidation);
	CBInt32ToArray(CB_DATA_ARRAY, CB_BRANCH_NUM_BLOCKS, validatorObj->branches[branch].numBlocks);
	CBInt32ToArray(CB_DATA_ARRAY, CB_BRANCH_PARENT_BLOCK_INDEX, validatorObj->branches[branch].parentBlockIndex);
	CB_DATA_ARRAY[CB_BRANCH_PARENT_BRANCH] = validatorObj->branches[branch].parentBranch;
	CBInt32ToArray(CB_DATA_ARRAY, CB_BRANCH_START_HEIGHT, validatorObj->branches[branch].startHeight);
	// Write data
	if (NOT CBDatabaseWriteValue(database, CB_BRANCH_KEY, CB_DATA_ARRAY, 21)) {
		CBLogError("Could not write branch information.");
		return false;
	}
	return true;
}
bool CBBlockChainStorageSaveUnspentOutput(void * validator, uint8_t * txHash, uint32_t outputIndex, uint32_t position, uint32_t length, bool increment){
	CBFullValidator * validatorObj = validator;
	CBDatabase * database = (CBDatabase *)validatorObj->storage;
	memcpy(CB_UNSPENT_OUTPUT_KEY + 2, txHash, 32);
	CBInt32ToArray(CB_UNSPENT_OUTPUT_KEY, 34, outputIndex);
	CBInt32ToArray(CB_DATA_ARRAY, CB_UNSPENT_OUTPUT_REF_POSITION, position);
	CBInt32ToArray(CB_DATA_ARRAY, CB_UNSPENT_OUTPUT_REF_LENGTH, length);
	// Add to storage
	if (NOT CBDatabaseWriteValue(database, CB_UNSPENT_OUTPUT_KEY, CB_DATA_ARRAY, 8)) {
		CBLogError("Could not write new unspent output reference into the database.");
		return false;
	}
	if (increment
		// For the transaction, increment the number of unspent outputs
		&& NOT CBBlockChainStorageChangeUnspentOutputsNum(database, txHash, +1)) {
		CBLogError("Could not increment the number of unspent outputs for a transaction.");
		return false;
	}
	return true;
}
bool CBBlockChainStorageSaveBlock(void * validator, void * block, uint8_t branch, uint32_t blockIndex){
	CBFullValidator * validatorObj = validator;
	CBBlock * blockObj = block;
	// Write the block data
	CB_BLOCK_KEY[2] = branch;
	CBInt32ToArray(CB_BLOCK_KEY, 3, blockIndex);
	uint8_t * dataParts[2] = {CBBlockGetHash(blockObj), CBByteArrayGetData(CBGetMessage(blockObj)->bytes)};
	uint32_t dataSizes[2] = {20, CBGetMessage(blockObj)->bytes->length};
	if (NOT CBDatabaseWriteConcatenatedValue((CBDatabase *)validatorObj->storage, CB_BLOCK_KEY, 2, dataParts, dataSizes)) {
		CBLogError("Could not write a block to the block-chain database.");
		return false;
	}
	// Write to the block hash index
	memcpy(CB_BLOCK_HASH_INDEX_KEY + 2, CBBlockGetHash(blockObj), 20);
	CB_DATA_ARRAY[CB_BLOCK_HASH_REF_BRANCH] = branch;
	CBInt32ToArray(CB_DATA_ARRAY, CB_BLOCK_HASH_REF_INDEX, blockIndex);
	if (NOT CBDatabaseWriteValue((CBDatabase *)validatorObj->storage, CB_BLOCK_HASH_INDEX_KEY, CB_DATA_ARRAY, 5)) {
		CBLogError("Could not write a block hash to the block-chain database block hash index.");
		return false;
	}
	return true;
}
예제 #11
0
bool CBAddressStorageDeleteAddress(uint64_t iself, void * address){
	CBAddressStore * self = (CBAddressStore *)iself;
	CBNetworkAddress * addrObj = address;
	memcpy(CB_ADDRESS_KEY + 1, CBByteArrayGetData(addrObj->ip), 16);
	CBInt16ToArray(CB_ADDRESS_KEY, 17, addrObj->port);
	// Remove address
	if (NOT CBDatabaseRemoveValue(CBGetDatabase(self), CB_ADDRESS_KEY)) {
		CBLogError("Could not remove an address from storage.");
		return false;
	}
	// Decrease number of addresses
	CBInt32ToArray(CB_DATA_ARRAY, 0, --self->numAddresses);
	if (NOT CBDatabaseWriteValue(CBGetDatabase(self), CB_ADDR_NUM_KEY, CB_DATA_ARRAY, 4)) {
		CBLogError("Could not write the new number of addresses to storage.");
		return false;
	}
	// Commit changes
	if (NOT CBDatabaseCommit(CBGetDatabase(self))) {
		CBLogError("Could not commit the removal of a network address.");
		return false;
	}
	return true;
}
예제 #12
0
uint64_t CBNewAddressStorage(char * dataDir){
	CBAddressStore * self = malloc(sizeof(*self));
	if (NOT self) {
		CBLogError("Could not create the address storage object.");
		return 0;
	}
	if (NOT CBInitDatabase(CBGetDatabase(self), dataDir, "addr")) {
		CBLogError("Could not create a database object for address storage.");
		free(self);
		return 0;
	}
	if (CBDatabaseGetLength(CBGetDatabase(self), CB_ADDR_NUM_KEY)) {
		// Get the number of addresses
		if (NOT CBDatabaseReadValue(CBGetDatabase(self), CB_ADDR_NUM_KEY, CB_DATA_ARRAY, 4, 0)) {
			CBLogError("Could not read the number of addresses from storage.");
			free(self);
			return 0;
		}
		self->numAddresses = CBArrayToInt32(CB_DATA_ARRAY, 0);
	}else{
		self->numAddresses = 0;
		// Insert zero number of addresses.
		CBInt32ToArray(CB_DATA_ARRAY, 0, 0);
		if (NOT CBDatabaseWriteValue(CBGetDatabase(self), CB_ADDR_NUM_KEY, CB_DATA_ARRAY, 4)) {
			CBLogError("Could not write the initial number of addresses to storage.");
			free(self);
			return 0;
		}
		// Commit changes
		if (NOT CBDatabaseCommit(CBGetDatabase(self))) {
			CBLogError("Could not commit the initial number of addresses to storage.");
			free(self);
			return 0;
		}
	}
	return (uint64_t) self;
}