예제 #1
0
uint8_t CBNetworkAddressDeserialise(CBNetworkAddress * self, bool timestamp){
	CBByteArray * bytes = CBGetMessage(self)->bytes;
	if (! bytes) {
		CBLogError("Attempting to deserialise a CBNetworkAddress with no bytes.");
		return 0;
	}
	if (bytes->length < 26 + timestamp * 4) {
		CBLogError("Attempting to deserialise a CBNetworkAddress with less bytes than required.");
		return 0;
	}
	uint8_t start;
	uint64_t twoHoursAgo = time(NULL) - 3600;
	if (timestamp) {
		// Make sure we do not set self->lastSeen later than one hour ago.
		self->lastSeen = CBByteArrayReadInt32(bytes, 0);
		if (self->lastSeen > twoHoursAgo)
			self->lastSeen = twoHoursAgo;
		start = 4;
	}else{
		self->lastSeen = twoHoursAgo;
		start = 0;
	}
	self->services = (CBVersionServices) CBByteArrayReadInt64(bytes, start);
	self->ip = CBNewByteArraySubReference(bytes, start + 8, 16);
	// Determine IP type
	self->type = CBGetIPType(CBByteArrayGetData(self->ip));
	self->port = CBByteArrayReadPort(bytes, start + 24);
	return start + 26;
}
bool CBBlockChainStorageLoadOrphan(void * validator, uint8_t orphanNum){
	CBFullValidator * validatorObj = validator;
	CBDatabase * database = (CBDatabase *)validatorObj->storage;
	CB_ORPHAN_KEY[2] = orphanNum;
	uint32_t len = CBDatabaseGetLength(database, CB_ORPHAN_KEY);
	CBByteArray * orphanData = CBNewByteArrayOfSize(len);
	if (NOT orphanData) {
		CBLogError("There was an error when initialising a byte array for an orphan.");
		return false;
	}
	if (NOT CBDatabaseReadValue(database, CB_ORPHAN_KEY, CBByteArrayGetData(orphanData), len, 0)) {
		CBLogError("There was an error when reading the data for an orphan.");
		CBReleaseObject(orphanData);
		return false;
	}
	validatorObj->orphans[orphanNum] = CBNewBlockFromData(orphanData);
        CBBlockDeserialise(validatorObj->orphans[orphanNum], true);
	if (NOT validatorObj->orphans[orphanNum]) {
		CBLogError("There was an error when creating a block object for an orphan.");
		CBReleaseObject(orphanData);
		return false;
	}
	CBReleaseObject(orphanData);
	return true;
}
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 CBBlockChainStorageLoadOutputs(void * validator, uint8_t * txHash, uint8_t ** data, uint32_t * dataAllocSize, uint32_t * position){
	CBFullValidator * validatorObj = validator;
	CBDatabase * database = (CBDatabase *)validatorObj->storage;
	memcpy(CB_TRANSACTION_INDEX_KEY + 2, txHash, 32);
	if (NOT CBDatabaseReadValue(database, CB_TRANSACTION_INDEX_KEY, CB_DATA_ARRAY, 14, 0)) {
		CBLogError("Could not read a transaction reference from the transaction index.");
		return false;
	}
	// Set position of outputs
	*position = CBArrayToInt32(CB_DATA_ARRAY, CB_TRANSACTION_REF_POSITION_OUPTUTS);
	// Get transaction to find position for output in the block
	// Reallocate transaction data memory if needed.
	if (CBArrayToInt32(CB_DATA_ARRAY, CB_TRANSACTION_REF_LENGTH_OUTPUTS) > *dataAllocSize) {
		*dataAllocSize = CBArrayToInt32(CB_DATA_ARRAY, CB_TRANSACTION_REF_LENGTH_OUTPUTS);
		*data = realloc(*data, *dataAllocSize);
		if (NOT *data) {
			CBLogError("Could not allocate memory for reading a transaction.");
			return false;
		}
	}
	// Read transaction from the block
	CB_BLOCK_KEY[2] = CB_DATA_ARRAY[CB_TRANSACTION_REF_BRANCH];
	memcpy(CB_BLOCK_KEY + 3, CB_DATA_ARRAY + CB_TRANSACTION_REF_BLOCK_INDEX, 4);
	if (NOT CBDatabaseReadValue(database, CB_BLOCK_KEY, *data, CBArrayToInt32(CB_DATA_ARRAY, CB_TRANSACTION_REF_LENGTH_OUTPUTS), CB_BLOCK_START + *position)) {
		CBLogError("Could not read a transaction from the block-chain database.");
		return false;
	}
	return true;
}
예제 #5
0
파일: CBBase58.c 프로젝트: GMD1987/cbitcoin
bool CBDecodeBase58Checked(CBBigInt * bi, char * str){
	if(NOT CBDecodeBase58(bi, str)) {
		CBLogError("Memory failure in CBDecodeBase58.");
		return false;
	}
	if (bi->length < 4){
		CBLogError("The string passed into CBDecodeBase58Checked decoded into data that was too short.");
		return false;
	}
	// Reverse bytes for checksum generation
	uint8_t * reversed = malloc(bi->length - 4);
	if (NOT reversed) {
		CBLogError("Cannot allocate %i bytes of memory in CBDecodeBase58Checked", bi->length - 4);
		return false;
	}
	for (uint8_t x = 4; x < bi->length; x++)
		reversed[bi->length - 1 - x] = bi->data[x];
	// The checksum uses SHA-256, twice, for some reason unknown to man.
	uint8_t checksum[32];
	uint8_t checksum2[32];
	CBSha256(reversed, bi->length - 4, checksum);
	free(reversed);
	CBSha256(checksum, 32, checksum2);
	bool ok = true;
	for (uint8_t x = 0; x < 4; x++)
		if (checksum2[x] != bi->data[3-x])
			ok = false;
	if (NOT ok){
		CBLogError("The data passed to CBDecodeBase58Checked is invalid. Checksum does not match.");
		return false;
	}
	return true;
}
예제 #6
0
uint32_t CBTransactionOutputSerialise(CBTransactionOutput * self){
	CBByteArray * bytes = CBGetMessage(self)->bytes;
	if (NOT bytes) {
		CBLogError("Attempting to serialise a CBTransactionInput with no bytes.");
		return 0;
	}
	if (NOT self->scriptObject){
		CBLogError("Attempting to serialise a CBTransactionOutput without scriptObject.");
		return 0;
	}
	CBVarInt scriptLen = CBVarIntFromUInt64(CBGetByteArray(self->scriptObject)->length);
	uint32_t reqLen = 8 + scriptLen.size + CBGetByteArray(self->scriptObject)->length;
	if (bytes->length < reqLen) {
		CBLogError("Attempting to serialise a CBTransactionOutput with less bytes than required. %i < %i", bytes->length, reqLen);
		return 0;
	}
	// Serialise data into the CBByteArray and rereference objects to this CBByteArray to save memory.
	CBByteArraySetInt64(bytes, 0, self->value);
	CBVarIntEncode(bytes, 8, scriptLen);
	CBByteArrayCopyByteArray(bytes, 8 + scriptLen.size, CBGetByteArray(self->scriptObject));
	CBByteArrayChangeReference(CBGetByteArray(self->scriptObject), bytes, 8 + scriptLen.size);
	// Ensure length is correct
	bytes->length = reqLen;
	// Is serialised.
	CBGetMessage(self)->serialised = true;
	return reqLen;
}
예제 #7
0
uint16_t CBChainDescriptorDeserialise(CBChainDescriptor * self){
	CBByteArray * bytes = CBGetMessage(self)->bytes;
	if (! bytes) {
		CBLogError("Attempting to deserialise a CBChainDescriptor with no bytes.");
		return 0;
	}
	if (bytes->length < 1) {
		CBLogError("Attempting to deserialise a CBChainDescriptor with no bytes");
		return 0;
	}
	CBVarInt hashNum = CBVarIntDecode(bytes, 0);
	if (hashNum.val > 500) {
		CBLogError("Attempting to deserialise a CBChainDescriptor with a var int over 500.");
		return 0;
	}
	if (bytes->length < hashNum.size + hashNum.val * 32) {
		CBLogError("Attempting to deserialise a CBChainDescriptor with less bytes than required for the hashes.");
		return 0;
	}
	// Deserialise each hash
	self->hashes = malloc(sizeof(*self->hashes) * (size_t)hashNum.val);
	self->hashNum = hashNum.val;
	uint16_t cursor = hashNum.size;
	for (uint16_t x = 0; x < self->hashNum; x++) {
		self->hashes[x] = CBNewByteArraySubReference(bytes, cursor, 32);
		cursor += 32;
	}
	return cursor;
}
예제 #8
0
uint32_t CBTransactionInputDeserialise(CBTransactionInput * self){
	CBByteArray * bytes = CBGetMessage(self)->bytes;
	if (! bytes) {
		CBLogError("Attempting to deserialise a CBTransactionInput with no bytes.");
		return 0;
	}
	if (bytes->length < 41) {
		CBLogError("Attempting to deserialise a CBTransactionInput with less than 41 bytes.");
		return 0;
	}
	CBVarInt scriptLen = CBVarIntDecode(bytes, 36);
	if (scriptLen.val > 10000) {
		CBLogError("Attempting to deserialise a CBTransactionInput with too big a script.");
		return 0;
	}
	uint32_t reqLen = (uint32_t)(40 + scriptLen.size + scriptLen.val);
	if (bytes->length < reqLen) {
		CBLogError("Attempting to deserialise a CBTransactionInput with less bytes than needed according to the length for the script. %i < %i", bytes->length, reqLen);
		return 0;
	}
	// Deserialise by subreferencing byte arrays and reading integers.
	self->prevOut.hash = CBByteArraySubReference(bytes, 0, 32);
	self->prevOut.index = CBByteArrayReadInt32(bytes, 32);
	self->scriptObject = CBNewScriptFromReference(bytes, 36 + scriptLen.size, (uint32_t) scriptLen.val);
	self->sequence = CBByteArrayReadInt32(bytes, (uint32_t) (36 + scriptLen.size + scriptLen.val));
	return reqLen;
}
예제 #9
0
파일: CBAlert.c 프로젝트: 01BTC10/cbitcoin
int CBAlertSerialiseSignature(CBAlert * self, int offset) {
	
	CBByteArray * bytes = CBGetMessage(self)->bytes;
	if (! bytes) {
		CBLogError("Attempting to serialise a CBAlert with no bytes.");
		return 0;
	}
	
	CBVarInt sigLen = CBVarIntFromUInt64(self->signature->length);
	if (bytes->length < offset + sigLen.size + sigLen.val) {
		CBLogError("Attempting to serialise a CBAlert with less bytes than required for the signature.");
		return 0;
	}
	
	CBByteArraySetVarInt(bytes, offset, sigLen);
	offset += sigLen.size;
	
	CBByteArrayCopyByteArray(bytes, offset, self->signature);
	CBByteArrayChangeReference(self->signature, bytes, offset);
	
	bytes->length = offset + (int)sigLen.val;
	
	CBGetMessage(self)->serialised = true;
	
	return bytes->length;
	
}
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;
}
예제 #11
0
uint8_t CBNetworkAddressSerialise(CBNetworkAddress * self, bool timestamp){
	CBByteArray * bytes = CBGetMessage(self)->bytes;
	if (! bytes) {
		CBLogError("Attempting to serialise a CBNetworkAddress with no bytes.");
		return 0;
	}
	if (bytes->length < 26 + timestamp * 4) {
		CBLogError("Attempting to serialise a CBNetworkAddress with less bytes than required.");
		return 0;
	}
	uint8_t cursor;
	if (timestamp) {
		CBByteArraySetInt32(bytes, 0, (uint32_t)(self->lastSeen - self->penalty));
		cursor = 4;
	}else cursor = 0;
	CBByteArraySetInt64(bytes, cursor, self->services);
	cursor += 8;
	CBByteArrayCopyByteArray(bytes, cursor, self->ip);
	CBByteArrayChangeReference(self->ip, bytes, cursor);
	cursor += 16;
	CBByteArraySetPort(bytes, cursor, self->port);
	bytes->length = cursor + 2;
	CBGetMessage(self)->serialised = true;
	return cursor + 2;
}
예제 #12
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;
}
예제 #14
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;
}
예제 #15
0
int CBInventoryDeserialise(CBInventory * self) {
	
	CBByteArray * bytes = CBGetMessage(self)->bytes;
	if (! bytes) {
		CBLogError("Attempting to deserialise a CBInventory with no bytes.");
		return CB_DESERIALISE_ERROR;
	}
	if (bytes->length < 37) {
		CBLogError("Attempting to deserialise a CBInventory with less bytes than required for one item.");
		return CB_DESERIALISE_ERROR;
	}
	
	CBVarInt itemNum = CBByteArrayReadVarInt(bytes, 0);
	if (itemNum.val > 50000) {
		CBLogError("Attempting to deserialise a CBInventory with a var int over 50000.");
		return CB_DESERIALISE_ERROR;
	}
	
	self->itemNum = 0;
	self->itemFront = NULL;
	
	// Run through the items and deserialise each one.
	int cursor = itemNum.size;
	
	for (int x = 0; x < itemNum.val; x++) {
		
		// Make new CBInventoryItem from the rest of the data.
		CBByteArray * data = CBByteArraySubReference(bytes, cursor, bytes->length-cursor);
		CBInventoryItem * item = CBNewInventoryItemFromData(data);
		
		// Deserialise
		int len = CBInventoryItemDeserialise(item);
		if (len == CB_DESERIALISE_ERROR){
			CBLogError("CBInventory cannot be deserialised because of an error with the CBInventoryItem number %u.", x);
			CBReleaseObject(data);
			return CB_DESERIALISE_ERROR;
		}
		
		// Take item
		CBInventoryTakeInventoryItem(self, item);
		
		// Adjust length
		data->length = len;
		CBReleaseObject(data);
		cursor += len;
		
	}
	
	return cursor;
}
예제 #16
0
uint32_t CBInventoryItemDeserialise(CBInventoryItem * self){
	CBByteArray * bytes = CBGetMessage(self)->bytes;
	if (NOT bytes) {
		CBLogError("Attempting to deserialise a CBInventoryItem with no bytes.");
		return 0;
	}
	if (bytes->length < 36) {
		CBLogError("Attempting to deserialise a CBInventoryItem with less than 36 bytes.");
		return 0;
	}
	self->type = CBByteArrayReadInt32(bytes, 0);
	self->hash = CBByteArraySubReference(bytes, 4, 32);
	if (NOT self->hash)
		return 0;
	return 36;
}
예제 #17
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);
}
예제 #18
0
파일: CBHDKeys.c 프로젝트: cedrou/cbitcoin
bool CBInitHDKeyFromData(CBHDKey * key, uint8_t * data, CBHDKeyVersion versionBytes, CBHDKeyType type){
	CBInitHDKey(key);
	// Set version bytes
	key->versionBytes = versionBytes;
	// Chain code
	memcpy(key->chainCode, data + 13, 32);
	if (type == CB_HD_KEY_TYPE_PRIVATE){
		// Private
		memcpy(key->keyPair->privkey, data + 46, 32);
		// Calculate public key
		CBKeyGetPublicKey(CBHDKeyGetPrivateKey(key), CBHDKeyGetPublicKey(key));
	}else
		// Assume public
		memcpy(CBHDKeyGetPublicKey(key), data + 45, 33);
	// Depth
	key->depth = data[4];
	if (key->depth == 0) {
		// Master
		key->childID.priv = false;
		key->childID.childNumber = 0;
		for (uint8_t x = 5; x < 9; x++)
			if (data[x] != 0) {
				CBLogError("The fingerprint of the master key is not zero.");
				return false;
			}
	}else{
		// Not master
		uint32_t childNum = CBArrayToInt32BigEndian(data, 9);
		key->childID.priv = childNum >> 31;
		key->childID.childNumber = childNum & 0x8fffffff;
	}
	return true;
}
예제 #19
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);
}
예제 #20
0
uint32_t CBBlockHeadersSerialise(CBBlockHeaders * self, bool force){
	CBByteArray * bytes = CBGetMessage(self)->bytes;
	if (! bytes) {
		CBLogError("Attempting to serialise a CBBlockHeaders with no bytes.");
		return 0;
	}
	if (bytes->length < 81 * self->headerNum) {
		CBLogError("Attempting to deserialise a CBBlockHeaders with less bytes than minimally required.");
		return 0;
	}
	CBVarInt num = CBVarIntFromUInt64(self->headerNum);
	CBVarIntEncode(bytes, 0, num);
	uint16_t cursor = num.size;
	for (uint16_t x = 0; x < num.val; x++) {
		if (! CBGetMessage(self->blockHeaders[x])->serialised // Serailise if not serialised yet.
			// Serialise if force is true.
			|| force
			// If the data shares the same data as the block headers message, re-serialise the block header, in case it got overwritten.
			|| CBGetMessage(self->blockHeaders[x])->bytes->sharedData == bytes->sharedData) {
			if (CBGetMessage(self->blockHeaders[x])->serialised)
				// Release old byte array
				CBReleaseObject(CBGetMessage(self->blockHeaders[x])->bytes);
			CBGetMessage(self->blockHeaders[x])->bytes = CBByteArraySubReference(bytes, cursor, bytes->length-cursor);
			if (! CBGetMessage(self->blockHeaders[x])->bytes) {
				CBLogError("Cannot create a new CBByteArray sub reference in CBBlockHeadersSerialise for the header number %u", x);
				return 0;
			}
			if (! CBBlockSerialise(self->blockHeaders[x], false, force)) { // false for no transactions.
				CBLogError("CBBlockHeaders cannot be serialised because of an error with the CBBlock number %u.", x);
				// Release CBByteArray objects to avoid problems overwritting pointer without release, if serialisation is tried again.
				for (uint8_t y = 0; y < x + 1; y++)
					CBReleaseObject(CBGetMessage(self->blockHeaders[y])->bytes);
				return 0;
			}
		}else{
			// Move serialsed data to one location
			CBByteArrayCopyByteArray(bytes, cursor, CBGetMessage(self->blockHeaders[x])->bytes);
			CBByteArrayChangeReference(CBGetMessage(self->blockHeaders[x])->bytes, bytes, cursor);
		}
		cursor += CBGetMessage(self->blockHeaders[x])->bytes->length;
	}
	// Ensure length is correct
	bytes->length = cursor;
	// Is now serialised
	CBGetMessage(self)->serialised = true;
	return cursor;
}
예제 #21
0
int CBBlockHeadersDeserialise(CBBlockHeaders * self) {
	
	CBByteArray * bytes = CBGetMessage(self)->bytes;
	if (! bytes) {
		CBLogError("Attempting to deserialise a CBBlockHeaders with no bytes.");
		return CB_DESERIALISE_ERROR;
	}
	if (bytes->length < 82) {
		CBLogError("Attempting to deserialise a CBBlockHeaders with less bytes than required for one header.");
		return CB_DESERIALISE_ERROR;
	}
	
	CBVarInt headerNum = CBByteArrayReadVarInt(bytes, 0);
	if (headerNum.val > 2000) {
		CBLogError("Attempting to deserialise a CBBlockHeaders with a var int over 2000.");
		return CB_DESERIALISE_ERROR;
	}
	
	// Deserialise each header
	self->headerNum = headerNum.val;
	int cursor = headerNum.size;
	
	for (int x = 0; x < headerNum.val; x++) {
		
		// Make new CBBlock from the rest of the data.
		CBByteArray * data = CBByteArraySubReference(bytes, cursor, bytes->length-cursor);
		self->blockHeaders[x] = CBNewBlockFromData(data);
		
		// Deserialise
		int len = CBBlockDeserialise(self->blockHeaders[x], false); // false for no transactions. Only the header.
		if (len == CB_DESERIALISE_ERROR){
			CBLogError("CBBlockHeaders cannot be deserialised because of an error with the CBBlock number %" PRIu16 ".", x);
			CBReleaseObject(data);
			return CB_DESERIALISE_ERROR;
		}
		
		// Adjust length
		data->length = len;
		CBReleaseObject(data);
		cursor += len;
		
	}
	
	return cursor;
	
}
예제 #22
0
int CBPingPongDeserialise(CBPingPong * self) {
	
	CBByteArray * bytes = CBGetMessage(self)->bytes;
	if (! bytes) {
		CBLogError("Attempting to deserialise a CBPingPong with no bytes.");
		return CB_DESERIALISE_ERROR;
	}
	if (bytes->length < 8) {
		CBLogError("Attempting to deserialise a CBPingPong with less than 8 bytes.");
		return CB_DESERIALISE_ERROR;
	}
	
	self->ID = CBByteArrayReadInt64(bytes, 0);
	
	return 8;
	
}
예제 #23
0
uint32_t CBInventoryItemSerialise(CBInventoryItem * self){
	CBByteArray * bytes = CBGetMessage(self)->bytes;
	if (NOT bytes) {
		CBLogError("Attempting to serialise a CBInventoryItem with no bytes.");
		return 0;
	}
	if (bytes->length < 36) {
		CBLogError("Attempting to serialise a CBInventoryItem with less than 36 bytes.");
		return 0;
	}
	CBByteArraySetInt32(bytes, 0, self->type);
	CBByteArrayCopyByteArray(bytes, 4, self->hash);
	CBByteArrayChangeReference(self->hash, bytes, 4);
	bytes->length = 36;
	CBGetMessage(self)->serialised = true;
	return 36;
}
bool CBBlockChainStorageLoadBranchWork(void * validator, uint8_t branchNum){
	CBFullValidator * validatorObj = validator;
	CBDatabase * database = (CBDatabase *)validatorObj->storage;
	// Get work
	CB_WORK_KEY[2] = branchNum;
	uint8_t workLen = CBDatabaseGetLength(database, CB_WORK_KEY);
	if (NOT CBBigIntAlloc(&validatorObj->branches[branchNum].work, workLen)){
		CBLogError("There was an error when allocating memory for a branch's work.");
		return false;
	}
	validatorObj->branches[branchNum].work.length = workLen;
	if (NOT CBDatabaseReadValue(database, CB_WORK_KEY, validatorObj->branches[branchNum].work.data, workLen, 0)) {
		CBLogError("There was an error when reading the work for a branch.");
		free(validatorObj->branches[branchNum].work.data);
		return false;
	}
	return true;
}
예제 #25
0
uint32_t CBNetworkAddressListSerialise(CBNetworkAddressList * self, bool force){
	CBByteArray * bytes = CBGetMessage(self)->bytes;
	if (! bytes) {
		CBLogError("Attempting to serialise a CBNetworkAddress with no bytes.");
		return 0;
	}
	CBVarInt num = CBVarIntFromUInt64(self->addrNum);
	if (bytes->length < (26 + self->timeStamps * 4) * self->addrNum + num.size) {
		CBLogError("Attempting to serialise a CBNetworkAddress without enough bytes.");
		return 0;
	}
	CBVarIntEncode(bytes, 0, num);
	uint16_t cursor = num.size;
	for (uint8_t x = 0; x < num.val; x++) {
		if (! CBGetMessage(self->addresses[x])->serialised // Serailise if not serialised yet.
			// Serialise if force is true.
			|| force
			// If the data shares the same data as this address broadcast, re-serialise the address, in case it got overwritten.
			|| CBGetMessage(self->addresses[x])->bytes->sharedData == bytes->sharedData
			|| (CBGetMessage(self->addresses[x])->bytes->length != 26) ^ self->timeStamps) {
			if (CBGetMessage(self->addresses[x])->serialised)
				// Release old byte array
				CBReleaseObject(CBGetMessage(self->addresses[x])->bytes);
			CBGetMessage(self->addresses[x])->bytes = CBByteArraySubReference(bytes, cursor, bytes->length-cursor);
			if (! CBNetworkAddressSerialise(self->addresses[x], self->timeStamps)) {
				CBLogError("CBNetworkAddress cannot be serialised because of an error with the CBNetworkAddress number %u.", x);
				// Release CBByteArray objects to avoid problems overwritting pointer without release, if serialisation is tried again.
				for (uint8_t y = 0; y < x + 1; y++)
					CBReleaseObject(CBGetMessage(self->addresses[y])->bytes);
				return 0;
			}
		}else{
			// Move serialsed data to one location
			CBByteArrayCopyByteArray(bytes, cursor, CBGetMessage(self->addresses[x])->bytes);
			CBByteArrayChangeReference(CBGetMessage(self->addresses[x])->bytes, bytes, cursor);
		}
		cursor += CBGetMessage(self->addresses[x])->bytes->length;
	}
	// Change bytes length
	bytes->length = cursor;
	// Is now serialised
	CBGetMessage(self)->serialised = true;
	return cursor;
}
예제 #26
0
bool CBAddressStorageLoadAddresses(uint64_t iself, void * addrMan){
	CBDatabase * database = (CBDatabase *)iself;
	CBAddressManager * addrManObj = addrMan;
	CBPosition it;
	// The first element shoudl be the number of addresses so get second element to begin with.
	if (CBAssociativeArrayGetElement(&database->index, &it, 1)) for(;;) {
		uint8_t * key = it.node->elements[it.index];
		CBIndexValue * val = (CBIndexValue *)(key + *key + 1);
		if (val->length) {
			// Is not deleted.
			// Read data
			uint64_t file = CBDatabaseGetFile(database, val->fileID);
			if (NOT file) {
				CBLogError("Could not open a file for loading a network address.");
				return false;
			}
			if (NOT CBFileSeek(file, val->pos)){
				CBLogError("Could not read seek a file to a network address.");
				return false;
			}
			if (NOT CBFileRead(file, CB_DATA_ARRAY, 20)) {
				CBLogError("Could not read a network address from a file.");
				return false;
			}
			// Create network address object and add to the address manager.
			CBByteArray * ip = CBNewByteArrayWithDataCopy(key + 1, 16);
			CBNetworkAddress * addr = CBNewNetworkAddress(CBArrayToInt64(CB_DATA_ARRAY, 0),
														  ip,
														  CBArrayToInt16(key, 17),
														  (CBVersionServices) CBArrayToInt64(CB_DATA_ARRAY, 8),
														  true);
			addr->penalty = CBArrayToInt32(CB_DATA_ARRAY, 16);
			if (NOT CBAddressManagerTakeAddress(addrManObj, addr)) {
				CBLogError("Could not create and add a network address to the address manager.");
				return false;
			}
			CBReleaseObject(ip);
		}
		if (CBAssociativeArrayIterate(&database->index, &it))
			break;
	}
	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;
}
예제 #28
0
파일: CBHDKeys.c 프로젝트: Jud/cbitcoin
bool CBKeyPairGenerate(CBKeyPair * keyPair){
	// Generate private key from a CSPRNG.
	if (!CBGet32RandomBytes(keyPair->privkey)) {
		CBLogError("Could not generate private key from 32 random bytes");
		return false;
	}
	// Get public key
	CBKeyGetPublicKey(keyPair->privkey, keyPair->pubkey.key);
	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;
}
예제 #30
0
파일: CBHDKeys.c 프로젝트: Jud/cbitcoin
CBHDKey * CBNewHDKeyFromData(uint8_t * data){
	CBHDKeyVersion versionBytes = CBArrayToInt32BigEndian(data, 0);
	CBHDKeyType type = CBHDKeyGetType(versionBytes);
	if (type == CB_HD_KEY_TYPE_UNKNOWN) {
		CBLogError("Unknown key type.");
		return NULL;
	}
	// Allocate memory for key
	CBHDKey * key = CBNewHDKey(type == CB_HD_KEY_TYPE_PRIVATE);
	return CBInitHDKeyFromData(key, data, versionBytes, type) ? key : NULL;
}