Exemplo n.º 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;
}
Exemplo n.º 2
0
void BRSendMessage(BRConnection *c, CBMessage *message, char *command) {
    /* partially adapted from examples/pingpong.c */
    char header[24] = {0}; /* zeros help us out places */
    
    memcpy(header + CB_MESSAGE_HEADER_TYPE, command, strlen(command));
    
    uint8_t hash[32];
    uint8_t hash2[32];
    if (message->bytes)
        CBSha256(CBByteArrayGetData(message->bytes), message->bytes->length, hash);
    else {
        /* Get the checksum right -- handles problem where checksum not calculated
         * for messages with no payload */
        CBSha256(NULL, 0, hash);
    }
    CBSha256(hash, 32, hash2);
    message->checksum[0] = hash2[0];
    message->checksum[1] = hash2[1];
    message->checksum[2] = hash2[2];
    message->checksum[3] = hash2[3];

    CBInt32ToArray(header, CB_MESSAGE_HEADER_NETWORK_ID, NETMAGIC);
    if (message->bytes) {
        CBInt32ToArray(header, CB_MESSAGE_HEADER_LENGTH, message->bytes->length);
    }
    memcpy(header + CB_MESSAGE_HEADER_CHECKSUM, message->checksum, 4);

    int sent = send(c->sock, header, 24, 0);
    if (sent < 0) {
        perror("send failed");
        exit(1);
    }
    if (sent != 24) {
        fprintf(stderr, "send sent %d, not 24 bytes\n", sent);
        exit(1);
    }
    if (message->bytes) {
        sent = send(c->sock, message->bytes->sharedData->data + message->bytes->offset,
                    message->bytes->length, 0);
        if (sent < 0) {
            perror("send failed");
            exit(1);
        }
        if (sent != message->bytes->length) {
            fprintf(stderr, "send sent %d, not %d bytes\n", sent, message->bytes->length);
            exit(1);
        }
    }

#ifdef BRDEBUG
    print_header(header);
    printf("message len: %d\n", message->bytes ? message->bytes->length : 0);
    printf("checksum: %x\n", *((uint32_t *) message->checksum));
    print_hex(message->bytes);
    printf("\n");
#endif
}
void * CBBlockChainStorageLoadUnspentOutput(void * validator, uint8_t * txHash, uint32_t outputIndex, bool * coinbase, uint32_t * outputHeight){
	CBFullValidator * validatorObj = validator;
	CBDatabase * database = (CBDatabase *)validatorObj->storage;
	// First read data for the unspent output key.
	memcpy(CB_UNSPENT_OUTPUT_KEY + 2, txHash, 32);
	CBInt32ToArray(CB_UNSPENT_OUTPUT_KEY, 34, outputIndex);
	if (NOT CBDatabaseReadValue(database, CB_UNSPENT_OUTPUT_KEY, CB_DATA_ARRAY, 8, 0)) {
		CBLogError("Cannot read unspent output information from the block chain database");
		return NULL;
	}
	uint32_t outputPosition = CBArrayToInt32(CB_DATA_ARRAY, CB_UNSPENT_OUTPUT_REF_POSITION);
	uint32_t outputLength = CBArrayToInt32(CB_DATA_ARRAY, CB_UNSPENT_OUTPUT_REF_LENGTH);
	// Now read data for the transaction
	memcpy(CB_TRANSACTION_INDEX_KEY + 2, txHash, 32);
	if (NOT CBDatabaseReadValue(database, CB_TRANSACTION_INDEX_KEY, CB_DATA_ARRAY, 14, 0)) {
		CBLogError("Cannot read a transaction reference from the transaction index.");
		return NULL;
	}
	uint8_t outputBranch = CB_DATA_ARRAY[CB_TRANSACTION_REF_BRANCH];
	uint32_t outputBlockIndex = CBArrayToInt32(CB_DATA_ARRAY, CB_TRANSACTION_REF_BLOCK_INDEX);
	// Set coinbase
	*coinbase = CB_DATA_ARRAY[CB_TRANSACTION_REF_IS_COINBASE];
	// Set output height
	*outputHeight = validatorObj->branches[outputBranch].startHeight + outputBlockIndex;
	// Get the output from storage
	CB_BLOCK_KEY[2] = outputBranch;
	CBInt32ToArray(CB_BLOCK_KEY, 3, outputBlockIndex);
	// Get output data
	CBByteArray * outputBytes = CBNewByteArrayOfSize(outputLength);
	if (NOT outputBytes) {
		CBLogError("Could not create  CBByteArray for an unspent output.");
		return NULL;
	}
	if (NOT CBDatabaseReadValue(database, CB_BLOCK_KEY, CBByteArrayGetData(outputBytes), outputLength, CB_BLOCK_START + outputPosition)) {
		CBLogError("Could not read an unspent output");
		CBReleaseObject(outputBytes);
		return NULL;
	}
	// Create output object
	CBTransactionOutput * output = CBNewTransactionOutputFromData(outputBytes);
	CBReleaseObject(outputBytes);
	if (NOT output) {
		CBLogError("Could not create an object for an unspent output");
		return NULL;
	}
	if (NOT CBTransactionOutputDeserialise(output)) {
		CBLogError("Could not deserialise an unspent output");
		return NULL;
	}
	return output;
}
void * CBBlockChainStorageLoadBlock(void * validator, uint32_t blockID, uint32_t branch){
	CBFullValidator * validatorObj = validator;
	CBDatabase * database = (CBDatabase *)validatorObj->storage;
	CB_BLOCK_KEY[2] = branch;
	CBInt32ToArray(CB_BLOCK_KEY, 3, blockID);
	uint32_t blockDataLen = CBDatabaseGetLength(database, CB_BLOCK_KEY);
	if (NOT blockDataLen)
		return NULL;
	blockDataLen -= CB_BLOCK_START;
	// Get block data
	CBByteArray * data = CBNewByteArrayOfSize(blockDataLen);
	if (NOT data) {
		CBLogError("Could not initialise a byte array for loading a block.");
		return NULL;
	}
	if (NOT CBDatabaseReadValue(database, CB_BLOCK_KEY, CBByteArrayGetData(data), blockDataLen, CB_BLOCK_START)){
		CBLogError("Could not read a block from the database.");
		CBReleaseObject(data);
		return NULL;
	}
	// Make and return the block
	CBBlock * block = CBNewBlockFromData(data);
	CBReleaseObject(data);
	if (NOT block) {
		CBLogError("Could not create a block object when loading a block.");
		return NULL;
	}
	return block;
}
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;
}
static void
send_version() 
{
    CBByteArray *ip = CBNewByteArrayWithDataCopy((uint8_t [16]){0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xFF, 0xFF, 127, 0, 0, 1}, 16);
    CBByteArray *ua = CBNewByteArrayFromString("cmsc417versiona", '\00');
    CBNetworkAddress * sourceAddr = CBNewNetworkAddress(0, ip, 0, CB_SERVICE_FULL_BLOCKS, false);
    int32_t vers = 70001;
    int nonce = rand();
    CBVersion * version = CBNewVersion(vers, CB_SERVICE_FULL_BLOCKS, time(NULL), &peer->base, sourceAddr, nonce, ua, 0);
    CBMessage *message = CBGetMessage(version);
    char header[24];
    memcpy(header + CB_MESSAGE_HEADER_TYPE, "version\0\0\0\0\0", 12);

    /* Compute length, serialized, and checksum */
    uint32_t len = CBVersionCalculateLength(version);
    message->bytes = CBNewByteArrayOfSize(len);
    len = CBVersionSerialise(version, false);
    if (message->bytes) {
        // Make checksum
        uint8_t hash[32];
        uint8_t hash2[32];
        CBSha256(CBByteArrayGetData(message->bytes), message->bytes->length, hash);
        CBSha256(hash, 32, hash2);
        message->checksum[0] = hash2[0];
        message->checksum[1] = hash2[1];
        message->checksum[2] = hash2[2];
        message->checksum[3] = hash2[3];
    }
    CBInt32ToArray(header, CB_MESSAGE_HEADER_NETWORK_ID, NETMAGIC);
    CBInt32ToArray(header, CB_MESSAGE_HEADER_LENGTH, message->bytes->length);
    // Checksum
    memcpy(header + CB_MESSAGE_HEADER_CHECKSUM, message->checksum, 4);

    // Send the header
    send(sd, header, 24, 0);
    
    // Send the message
    printf("message len: %d\n", message->bytes->length);
    printf("checksum: %x\n", *((uint32_t *) message->checksum));
    send(sd, message->bytes->sharedData->data+message->bytes->offset, message->bytes->length, 0);
    print_hex(message->bytes);
}
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;
}
uint32_t CBBlockChainStorageGetBlockTarget(void * validator, uint8_t branch, uint32_t blockIndex){
	CBFullValidator * validatorObj = validator;
	CBDatabase * database = (CBDatabase *)validatorObj->storage;
	CB_BLOCK_KEY[2] = branch;
	CBInt32ToArray(CB_BLOCK_KEY, 3, blockIndex);
	if (NOT CBDatabaseReadValue(database, CB_BLOCK_KEY, CB_DATA_ARRAY, 4, CB_BLOCK_TARGET)) {
		CBLogError("Could not read the target for a block.");
		return 0;
	}
	return CBArrayToInt32(CB_DATA_ARRAY, 0);
}
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 CBBlockChainStorageMoveBlock(void * validator, uint8_t branch, uint32_t blockIndex, uint8_t newBranch, uint32_t newIndex){
	CBFullValidator * validatorObj = validator;
	CBDatabase * database = (CBDatabase *)validatorObj->storage;
	CB_BLOCK_KEY[2] = branch;
	CBInt32ToArray(CB_BLOCK_KEY, 3, blockIndex);
	CB_NEW_BLOCK_KEY[2] = newBranch;
	if (NOT CBDatabaseChangeKey(database, CB_BLOCK_KEY, CB_NEW_BLOCK_KEY)) {
		CBLogError("Could not move a block location in the block-chain database.");
		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 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;
}
bool CBBlockChainStorageDeleteUnspentOutput(void * validator, uint8_t * txHash, uint32_t outputIndex, bool decrement){
	CBFullValidator * validatorObj = validator;
	CBDatabase * database = (CBDatabase *)validatorObj->storage;
	// Place transaction hash into the key
	memcpy(CB_UNSPENT_OUTPUT_KEY + 2, txHash, 32);
	// Place output index into the key
	CBInt32ToArray(CB_UNSPENT_OUTPUT_KEY, 34, outputIndex);
	// Remove from storage
	if (NOT CBDatabaseRemoveValue(database, CB_UNSPENT_OUTPUT_KEY)) {
		CBLogError("Could not remove an unspent output reference from storage.");
		return false;
	}
	if (decrement
		// For the transaction, decrement the number of unspent outputs
		&& NOT CBBlockChainStorageChangeUnspentOutputsNum(database, txHash, -1)) {
		CBLogError("Could not decrement the number of unspent outputs for a transaction.");
		return false;
	}
	return true;
}
Exemplo n.º 14
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;
}
Exemplo n.º 15
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;
}
bool CBBlockChainStorageDeleteBlock(void * validator, uint8_t branch, uint32_t blockIndex){
	CBFullValidator * validatorObj = validator;
	CBDatabase * database = (CBDatabase *)validatorObj->storage;
	// Delete from storage
	CB_BLOCK_KEY[2] = branch;
	CBInt32ToArray(CB_BLOCK_KEY, 3, blockIndex);
	// Get hash
	if (NOT CBDatabaseReadValue(database, CB_BLOCK_KEY, CB_DATA_ARRAY, 20, CB_BLOCK_HASH)) {
		CBLogError("Could not obtain a block hash from the block chain database.");
		return false;
	}
	// Remove data
	if (NOT CBDatabaseRemoveValue(database, CB_BLOCK_KEY)){
		CBLogError("Could not remove block value from database.");
		return false;
	}
	// Remove hash index reference
	memcpy(CB_BLOCK_HASH_INDEX_KEY + 2, CB_DATA_ARRAY, 20);
	if (NOT CBDatabaseRemoveValue(database, CB_BLOCK_HASH_INDEX_KEY)){
		CBLogError("Could not remove block hash index reference from database.");
		return false;
	}
	return true;
}
bool CBBlockChainStorageUnspentOutputExists(void * validator, uint8_t * txHash, uint32_t outputIndex){
	CBFullValidator * validatorObj = validator;
	memcpy(CB_UNSPENT_OUTPUT_KEY + 2, txHash, 32);
	CBInt32ToArray(CB_UNSPENT_OUTPUT_KEY, 34, outputIndex);
	return CBDatabaseGetLength((CBDatabase *)validatorObj->storage, CB_UNSPENT_OUTPUT_KEY);
}