uint32_t CBTransactionInputSerialise(CBTransactionInput * self){
	CBByteArray * bytes = CBGetMessage(self)->bytes;
	if (NOT bytes) {
		CBGetMessage(self)->onErrorReceived(CB_ERROR_MESSAGE_SERIALISATION_NULL_BYTES,"Attempting to serialise a CBTransactionInput with no bytes.");
		return 0;
	}
	if (NOT self->prevOut.hash){
		CBGetMessage(self)->onErrorReceived(CB_ERROR_MESSAGE_SERIALISATION_BAD_DATA,"Attempting to serialise a CBTransactionInput without prevOut.hash.");
		return 0;
	}
	if (NOT self->scriptObject){
		CBGetMessage(self)->onErrorReceived(CB_ERROR_MESSAGE_SERIALISATION_BAD_DATA,"Attempting to serialise a CBTransactionInput without scriptObject.");
		return 0;
	}
	CBVarInt scriptLen = CBVarIntFromUInt64(CBGetByteArray(self->scriptObject)->length);
	uint32_t reqLen = 40 + scriptLen.size + CBGetByteArray(self->scriptObject)->length;
	if (bytes->length < reqLen) {
		CBGetMessage(self)->onErrorReceived(CB_ERROR_MESSAGE_SERIALISATION_BAD_BYTES,"Attempting to serialise a CBTransactionInput with less bytes than required. %i < %i\n",bytes->length, reqLen);
		return 0;
	}
	// Serialise data into the CBByteArray and rereference objects to this CBByteArray to save memory.
	CBByteArrayCopyByteArray(bytes, 0, self->prevOut.hash);
	CBByteArrayChangeReference(self->prevOut.hash, bytes, 0);
	CBByteArraySetInt32(bytes, 32, self->prevOut.index);
	CBVarIntEncode(bytes, 36, scriptLen);
	CBByteArrayCopyByteArray(bytes, 36 + scriptLen.size,CBGetByteArray(self->scriptObject));
	CBByteArrayChangeReference(CBGetByteArray(self->scriptObject),bytes,36 + scriptLen.size);
	CBByteArraySetInt32(bytes,36 + scriptLen.size + CBGetByteArray(self->scriptObject)->length,self->sequence);
	CBGetMessage(self)->serialised = true;
	return reqLen;
}
Exemple #2
0
uint32_t CBTransactionInputSerialise(CBTransactionInput * self){
	CBByteArray * bytes = CBGetMessage(self)->bytes;
	if (! bytes) {
		CBLogError("Attempting to serialise a CBTransactionInput with no bytes.");
		return 0;
	}
	if (! self->prevOut.hash){
		CBLogError("Attempting to serialise a CBTransactionInput without prevOut.hash.");
		return 0;
	}
	if (! self->scriptObject){
		CBLogError("Attempting to serialise a CBTransactionInput without scriptObject.");
		return 0;
	}
	CBVarInt scriptLen = CBVarIntFromUInt64(CBGetByteArray(self->scriptObject)->length);
	uint32_t reqLen = 40 + scriptLen.size + CBGetByteArray(self->scriptObject)->length;
	if (bytes->length < reqLen) {
		CBLogError("Attempting to serialise a CBTransactionInput 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.
	CBByteArrayCopyByteArray(bytes, 0, self->prevOut.hash);
	CBByteArrayChangeReference(self->prevOut.hash, bytes, 0);
	CBByteArraySetInt32(bytes, 32, self->prevOut.index);
	CBVarIntEncode(bytes, 36, scriptLen);
	CBByteArrayCopyByteArray(bytes, 36 + scriptLen.size, CBGetByteArray(self->scriptObject));
	CBByteArrayChangeReference(CBGetByteArray(self->scriptObject), bytes, 36 + scriptLen.size);
	CBByteArraySetInt32(bytes, 36 + scriptLen.size + CBGetByteArray(self->scriptObject)->length, self->sequence);
	// Ensure length is correct
	bytes->length = reqLen;
	// Is serialised.
	CBGetMessage(self)->serialised = true;
	return reqLen;
}
Exemple #3
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;
}
Exemple #4
0
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;
	
}
Exemple #5
0
uint32_t CBInventoryItemSerialise(CBInventoryItem * self){
	CBByteArray * bytes = CBGetMessage(self)->bytes;
	if (NOT bytes) {
		CBGetMessage(self)->logError("Attempting to serialise a CBInventoryItem with no bytes.");
		return 0;
	}
	if (bytes->length < 36) {
		CBGetMessage(self)->logError("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);
	CBGetMessage(self)->serialised = true;
	return 36;
}
Exemple #6
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;
}
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;
}
Exemple #8
0
uint32_t CBBlockHeadersSerialise(CBBlockHeaders * self, bool force) {
    CBByteArray * bytes = CBGetMessage(self)->bytes;
    if (NOT bytes) {
        CBGetMessage(self)->logError("Attempting to serialise a CBBlockHeaders with no bytes.");
        return 0;
    }
    if (bytes->length < 81 * self->headerNum) {
        CBGetMessage(self)->logError("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 (force && CBGetMessage(self->blockHeaders[x])->serialised)
            CBReleaseObject(CBGetMessage(self->blockHeaders[x])->bytes);
        if (NOT CBGetMessage(self->blockHeaders[x])->serialised || force) {
            CBGetMessage(self->blockHeaders[x])->bytes = CBByteArraySubReference(bytes, cursor, bytes->length-cursor);
            if (NOT CBGetMessage(self->blockHeaders[x])->bytes) {
                CBGetMessage(self)->logError("Cannot create a new CBByteArray sub reference in CBBlockHeadersSerialise for the header number %u",x);
                return 0;
            }
            uint32_t len = CBBlockSerialise(self->blockHeaders[x], false, force); // false for no transactions.
            if (NOT len) {
                CBGetMessage(self)->logError("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;
            }
            CBGetMessage(self->blockHeaders[x])->bytes->length = len;
        } else if (CBGetMessage(self->blockHeaders[x])->bytes->sharedData != bytes->sharedData) {
            // 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;
    }
    CBGetMessage(self)->serialised = true;
    return cursor;
}
uint32_t CBInventoryBroadcastSerialise(CBInventoryBroadcast * self, bool force){
	CBByteArray * bytes = CBGetMessage(self)->bytes;
	if (NOT bytes) {
		CBGetMessage(self)->onErrorReceived(CB_ERROR_MESSAGE_SERIALISATION_NULL_BYTES,"Attempting to serialise a CBInventoryBroadcast with no bytes.");
		return 0;
	}
	CBVarInt num = CBVarIntFromUInt64(self->itemNum);
	if (bytes->length < num.size + 36 * self->itemNum) {
		CBGetMessage(self)->onErrorReceived(CB_ERROR_MESSAGE_DESERIALISATION_BAD_BYTES,"Attempting to deserialise a CBInventoryBroadcast with less bytes than required.");
		return 0;
	}
	CBVarIntEncode(bytes, 0, num);
	uint16_t cursor = num.size;
	for (uint16_t x = 0; x < num.val; x++) {
		if (force && CBGetMessage(self->items[x])->serialised)
			CBReleaseObject(CBGetMessage(self->items[x])->bytes);
		if (NOT CBGetMessage(self->items[x])->serialised || force) {
			CBGetMessage(self->items[x])->bytes = CBByteArraySubReference(bytes, cursor, bytes->length-cursor);
			if (NOT CBGetMessage(self->items[x])->bytes) {
				CBGetMessage(self)->onErrorReceived(CB_ERROR_INIT_FAIL,"Cannot create a new CBByteArray sub reference in CBInventoryBroadcastSerialise");
				return 0;
			}
			uint32_t len = CBInventoryItemSerialise(self->items[x]);
			if (NOT len) {
				CBGetMessage(self)->onErrorReceived(CB_ERROR_MESSAGE_SERIALISATION_BAD_BYTES,"CBInventoryBroadcast cannot be serialised because of an error with the CBInventoryItem 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->items[y])->bytes);
				return 0;
			}
			CBGetMessage(self->items[x])->bytes->length = len;
		}else if (CBGetMessage(self->items[x])->bytes->sharedData != bytes->sharedData){
			// Move serialsed data to one location
			CBByteArrayCopyByteArray(bytes, cursor, CBGetMessage(self->items[x])->bytes);
			CBByteArrayChangeReference(CBGetMessage(self->items[x])->bytes, bytes, cursor);
		}
		cursor += CBGetMessage(self->items[x])->bytes->length;
	}
	CBGetMessage(self)->serialised = true;
	return cursor;
}
Exemple #10
0
uint16_t CBChainDescriptorSerialise(CBChainDescriptor * self){
	CBByteArray * bytes = CBGetMessage(self)->bytes;
	if (! bytes) {
		CBLogError("Attempting to serialise a CBChainDescriptor with no bytes.");
		return 0;
	}
	CBVarInt hashNum = CBVarIntFromUInt64(self->hashNum);
	if (bytes->length < hashNum.size + self->hashNum * 32) {
		CBLogError("Attempting to serialise a CBChainDescriptor with less bytes than required for the hashes.");
		return 0;
	}
	CBVarIntEncode(bytes, 0, hashNum);
	uint16_t cursor = hashNum.size;
	for (uint16_t x = 0; x < self->hashNum; x++) {
		CBByteArrayCopyByteArray(bytes, cursor, self->hashes[x]);
		CBByteArrayChangeReference(self->hashes[x], bytes, cursor);
		cursor += 32;
	}
	CBGetMessage(self)->serialised = true;
	return cursor;
}
uint32_t CBAddressBroadcastSerialise(CBAddressBroadcast * self, bool force){
	CBByteArray * bytes = CBGetMessage(self)->bytes;
	if (NOT bytes) {
		CBGetMessage(self)->onErrorReceived(CB_ERROR_MESSAGE_SERIALISATION_NULL_BYTES,"Attempting to serialise a CBAddressBroadcast with no bytes.");
		return 0;
	}
	if (bytes->length < (26 + self->timeStamps * 4) * self->addrNum) {
		CBGetMessage(self)->onErrorReceived(CB_ERROR_MESSAGE_SERIALISATION_BAD_BYTES,"Attempting to serialise a CBAddressBroadcast without enough bytes.");
		return 0;
	}
	CBVarInt num = CBVarIntFromUInt64(self->addrNum);
	CBVarIntEncode(bytes, 0, num);
	uint16_t cursor = num.size;
	for (uint8_t x = 0; x < num.val; x++) {
		if (force && CBGetMessage(self->addresses[x])->serialised)
			CBReleaseObject(CBGetMessage(self->addresses[x])->bytes);
		if (NOT CBGetMessage(self->addresses[x])->serialised || force) {
			CBGetMessage(self->addresses[x])->bytes = CBByteArraySubReference(bytes, cursor, bytes->length-cursor);
			uint32_t len = CBNetworkAddressSerialise(self->addresses[x],self->timeStamps);
			if (NOT len) {
				CBGetMessage(self)->onErrorReceived(CB_ERROR_MESSAGE_SERIALISATION_BAD_BYTES,"CBAddressBroadcast 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;
			}
			CBGetMessage(self->addresses[x])->bytes->length = len;
		}else if (CBGetMessage(self->addresses[x])->bytes->sharedData != bytes->sharedData){
			// 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;
	}
	CBGetMessage(self)->serialised = true;
	return cursor;
}
Exemple #12
0
int CBInventorySerialise(CBInventory * self, bool force) {
	
	CBByteArray * bytes = CBGetMessage(self)->bytes;
	if (! bytes) {
		CBLogError("Attempting to serialise a CBInventory with no bytes.");
		return 0;
	}
	
	CBVarInt num = CBVarIntFromUInt64(self->itemNum);
	if (bytes->length < num.size + 36 * self->itemNum) {
		CBLogError("Attempting to deserialise a CBInventory with less bytes than required.");
		return 0;
	}
	CBByteArraySetVarInt(bytes, 0, num);
	
	int cursor = num.size;
	
	for (CBInventoryItem * item = self->itemFront; item != NULL; item = item->next) {
		
		if (! CBGetMessage(item)->serialised  // Serialise if not serialised yet.
			// Serialise if force is true.
			|| force
			// If the data shares the same data as the inventory boradcast, re-serialise the inventory item, in case it got overwritten.
			|| CBGetMessage(item)->bytes->sharedData == bytes->sharedData) {
			
			if (CBGetMessage(item)->serialised)
				// Release old byte array
				CBReleaseObject(CBGetMessage(item)->bytes);
			
			CBGetMessage(item)->bytes = CBByteArraySubReference(bytes, cursor, bytes->length-cursor);

			if (! CBInventoryItemSerialise(item)) {
				
				CBLogError("CBInventory cannot be serialised because of an error with an CBInventoryItem.");
				
				// Release CBByteArray objects to avoid problems overwritting pointer without release, if serialisation is tried again.
				for (CBInventoryItem * item2 = self->itemFront; ; item2 = item->next){
					CBReleaseObject(item2);
					if (item2 == item)
						break;
				}
				
				return 0;
				
			}
			
		}else{
			// Move serialsed data to one location
			CBByteArrayCopyByteArray(bytes, cursor, CBGetMessage(item)->bytes);
			CBByteArrayChangeReference(CBGetMessage(item)->bytes, bytes, cursor);
		}
		
		cursor += CBGetMessage(item)->bytes->length;
	}
	
	// Ensure length is correct
	bytes->length = cursor;
	
	// Is now serialised.
	CBGetMessage(self)->serialised = true;
	
	return cursor;
	
}
Exemple #13
0
uint32_t CBTransactionSerialise(CBTransaction * self, bool force){
	CBByteArray * bytes = CBGetMessage(self)->bytes;
	if (NOT bytes) {
		CBLogError("Attempting to serialise a CBTransaction with no bytes. Now that you think about it, that was a bit stupid wasn't it?");
		return 0;
	}
	if (NOT self->inputNum || NOT self->outputNum) {
		CBLogError("Attempting to serialise a CBTransaction with an empty output or input list.");
		return 0;
	}
	CBVarInt inputNum = CBVarIntFromUInt64(self->inputNum);
	CBVarInt outputNum = CBVarIntFromUInt64(self->outputNum);
	uint32_t cursor = 4 + inputNum.size;
	if (bytes->length < cursor + 5) {
		CBLogError("Attempting to serialise a CBTransaction with less bytes than required. %i < %i\n", bytes->length, cursor + 5);
		return 0;
	}
	// Serialise data into the CBByteArray and rereference objects to this CBByteArray to save memory.
	CBByteArraySetInt32(bytes, 0, self->version);
	CBVarIntEncode(bytes, 4, inputNum);
	for (uint32_t x = 0; x < self->inputNum; x++) {
		if (NOT CBGetMessage(self->inputs[x])->serialised // Serailise if not serialised yet.
			// Serialise if force is true.
			|| force
			// If the data shares the same data as this transaction, re-serialise the input, in case it got overwritten.
			|| CBGetMessage(self->inputs[x])->bytes->sharedData == bytes->sharedData) {
			if (CBGetMessage(self->inputs[x])->serialised)
				// Release old byte array
				CBReleaseObject(CBGetMessage(self->inputs[x])->bytes);
			CBGetMessage(self->inputs[x])->bytes = CBByteArraySubReference(bytes, cursor, bytes->length-cursor);
			if (NOT CBGetMessage(self->inputs[x])->bytes) {
				CBLogError("Cannot create a new CBByteArray sub reference in CBTransactionSerialise for input number %u", x);
				return 0;
			}
			if (NOT CBTransactionInputSerialise(self->inputs[x])) {
				CBLogError("CBTransaction cannot be serialised because of an error with the input number %u.", x);
				// Release CBByteArray objects to avoid problems overwritting pointer without release, if serialisation is tried again.
				for (uint32_t y = 0; y < x + 1; y++)
					CBReleaseObject(CBGetMessage(self->inputs[y])->bytes);
				return 0;
			}
		}else{
			// Move serialsed data to one location
			CBByteArrayCopyByteArray(bytes, cursor, CBGetMessage(self->inputs[x])->bytes);
			CBByteArrayChangeReference(CBGetMessage(self->inputs[x])->bytes, bytes, cursor);
		}
		cursor += CBGetMessage(self->inputs[x])->bytes->length;
	}
	if (bytes->length < cursor + 5) { // Check room for output number and lockTime.
		CBLogError("Attempting to serialise a CBTransaction with less bytes than required for output number and the lockTime. %i < %i", bytes->length, cursor + 5);
		return 0;
	}
	CBVarIntEncode(bytes, cursor, outputNum);
	cursor += outputNum.size;
	for (uint32_t x = 0; x < self->outputNum; x++) {
		if (NOT CBGetMessage(self->outputs[x])->serialised // Serailise if not serialised yet.
			// Serialise if force is true.
			|| force
			// If the data shares the same data as this transaction, re-serialise the output, in case it got overwritten.
			|| CBGetMessage(self->outputs[x])->bytes->sharedData == bytes->sharedData) {
			if (CBGetMessage(self->outputs[x])->serialised)
				// Release old byte array
				CBReleaseObject(CBGetMessage(self->outputs[x])->bytes);
			CBGetMessage(self->outputs[x])->bytes = CBByteArraySubReference(bytes, cursor, bytes->length-cursor);
			if (NOT CBGetMessage(self->outputs[x])->bytes) {
				CBLogError("Cannot create a new CBByteArray sub reference in CBTransactionSerialise for output number %u", x);
				return 0;
			}
			if (NOT CBTransactionOutputSerialise(self->outputs[x])) {
				CBLogError("CBTransaction cannot be serialised because of an error with the output number %u.", x);
				// Release CBByteArray objects to avoid problems overwritting pointer without release, if serialisation is tried again.
				for (uint32_t y = 0; y < self->inputNum; y++)
					CBReleaseObject(CBGetMessage(self->inputs[y])->bytes);
				for (uint32_t y = 0; y < x + 1; y++)
					CBReleaseObject(CBGetMessage(self->outputs[y])->bytes);
				return 0;
			}
		}else{
			// Move serialsed data to one location
			CBByteArrayCopyByteArray(bytes, cursor, CBGetMessage(self->outputs[x])->bytes);
			CBByteArrayChangeReference(CBGetMessage(self->outputs[x])->bytes, bytes, cursor);
		}
		cursor += CBGetMessage(self->outputs[x])->bytes->length;
	}
	if (bytes->length < cursor + 4) { // Check room for lockTime.
		CBLogError("Attempting to serialise a CBTransaction with less bytes than required for the lockTime. %i < %i\n", bytes->length, cursor + 4);
		// Release CBByteArray objects to avoid problems overwritting pointer without release, if serialisation is tried again.
		for (uint32_t y = 0; y < self->inputNum; y++)
			CBReleaseObject(CBGetMessage(self->inputs[y])->bytes);
		for (uint32_t y = 0; y < self->outputNum; y++)
			CBReleaseObject(CBGetMessage(self->outputs[y])->bytes);
		return 0;
	}
	CBByteArraySetInt32(bytes, cursor, self->lockTime);
	// Ensure length is correct
	bytes->length = cursor + 4;
	// Is serialised
	CBGetMessage(self)->serialised = true;
	// Make the hash not set for this serialisation.
	self->hashSet = false;
	return cursor + 4;
}
Exemple #14
0
CBGetHashReturn CBTransactionGetInputHashForSignature(void * vself, CBByteArray * prevOutSubScript, uint32_t input, CBSignType signType, uint8_t * hash){
	CBTransaction * self= vself;
	if (self->inputNum < input + 1) {
		CBLogError("Receiving transaction hash to sign cannot be done for because the input index goes past the number of inputs.");
		return CB_TX_HASH_BAD;
	}
	uint8_t last5Bits = (signType & 0x1f); // For some reason this is what the C++ client does.
	CBVarInt prevOutputSubScriptVarInt = CBVarIntFromUInt64(prevOutSubScript->length);
	uint32_t sizeOfData = 12 + prevOutSubScript->length + prevOutputSubScriptVarInt.size; // Version, lock time and the sign type make up 12 bytes.
	if (signType & CB_SIGHASH_ANYONECANPAY) {
		sizeOfData += 41; // Just this one input. 32 bytes for outPointerHash, 4 for outPointerIndex, 4 for sequence and one for the *inputNum* var int
	}else{
		sizeOfData += CBVarIntSizeOf(self->inputNum) + self->inputNum * 41 - 1; // All inputs with 1 byte var int except one.
	}
	if (last5Bits == CB_SIGHASH_NONE){
		sizeOfData++; // Just for the CBVarInt and no outputs.
	}else if ((signType & 0x1f) == CB_SIGHASH_SINGLE){
		if (self->outputNum < input + 1) {
			CBLogError("Receiving transaction hash to sign cannot be done for CB_SIGHASH_SINGLE because there are not enough outputs.");
			return CB_TX_HASH_BAD;
		}
		sizeOfData += CBVarIntSizeOf(input + 1) + input * 9; // For outputs up to the input index
		// The size for the output at the input index.
		uint32_t len = CBGetByteArray(self->outputs[input]->scriptObject)->length;
		sizeOfData += 8 + CBVarIntSizeOf(len) + len;
	}else{ // All outputs. Default to SIGHASH_ALL
		sizeOfData += CBVarIntSizeOf(self->outputNum);
		for (uint32_t x = 0; x < self->outputNum; x++) {
			uint32_t len = CBGetByteArray(self->outputs[x]->scriptObject)->length;
			sizeOfData += 8 + CBVarIntSizeOf(len) + len;
		}
	}
	CBByteArray * data = CBNewByteArrayOfSize(sizeOfData);
	if (NOT data)
		return CB_TX_HASH_ERR;
	CBByteArraySetInt32(data, 0, self->version);
	// Copy input data. Scripts are not copied for the inputs.
	uint32_t cursor;
	if (signType & CB_SIGHASH_ANYONECANPAY) {
		CBVarIntEncode(data, 4, CBVarIntFromUInt64(1)); // Only the input the signature is for.
		CBByteArrayCopyByteArray(data, 5, self->inputs[input]->prevOut.hash);
		CBByteArraySetInt32(data, 37, self->inputs[input]->prevOut.index);
		// Add prevOutSubScript
		CBVarIntEncode(data, 41, prevOutputSubScriptVarInt);
		cursor = 41 + prevOutputSubScriptVarInt.size;
		CBByteArrayCopyByteArray(data, cursor, prevOutSubScript);
		cursor += prevOutSubScript->length;
		CBByteArraySetInt32(data, cursor, self->inputs[input]->sequence);
		cursor += 4;
	}else{
		CBVarInt inputNum = CBVarIntFromUInt64(self->inputNum);
		CBVarIntEncode(data, 4, inputNum);
		cursor = 4 + inputNum.size;
		for (uint32_t x = 0; x < self->inputNum; x++) {
			CBByteArrayCopyByteArray(data, cursor, self->inputs[x]->prevOut.hash);
			cursor += 32;
			CBByteArraySetInt32(data, cursor, self->inputs[x]->prevOut.index);
			cursor += 4;
			// Add prevOutSubScript if the input is for the signature.
			if (x == input) {
				CBVarIntEncode(data, cursor, prevOutputSubScriptVarInt);
				cursor += prevOutputSubScriptVarInt.size;
				CBByteArrayCopyByteArray(data, cursor, prevOutSubScript);
				cursor += prevOutSubScript->length;
			}else{
				CBVarIntEncode(data, cursor, CBVarIntFromUInt64(0));
				cursor++;
			}
			if ((signType == CB_SIGHASH_NONE || signType == CB_SIGHASH_SINGLE) && x != input) {
				CBByteArraySetInt32(data, cursor, 0);
			}
			else // SIGHASH_ALL or input index for signing sequence
				CBByteArraySetInt32(data, cursor, self->inputs[x]->sequence);
			cursor += 4;
		}
	}
	// Copy output data
	if (last5Bits == CB_SIGHASH_NONE){
		CBVarInt varInt = CBVarIntFromUInt64(0);
		CBVarIntEncode(data, cursor, varInt);
		cursor++;
	}else if (last5Bits == CB_SIGHASH_SINGLE){
		CBVarInt varInt = CBVarIntFromUInt64(input + 1);
		CBVarIntEncode(data, cursor, varInt);
		cursor += varInt.size;
		for (uint32_t x = 0; x < input; x++) {
			CBByteArraySetInt64(data, cursor, CB_OUTPUT_VALUE_MINUS_ONE);
			cursor += 8;
			CBVarIntEncode(data, cursor, CBVarIntFromUInt64(0));
			cursor++;
		}
		CBByteArraySetInt64(data, cursor, self->outputs[input]->value);
		cursor += 8;
		varInt = CBVarIntFromUInt64(CBGetByteArray(self->outputs[input]->scriptObject)->length);
		CBVarIntEncode(data, cursor, varInt);
		cursor += varInt.size;
		CBByteArrayCopyByteArray(data, cursor, CBGetByteArray(self->outputs[input]->scriptObject));
		cursor += varInt.val;
	}else{ // SIGHASH_ALL
		CBVarInt varInt = CBVarIntFromUInt64(self->outputNum);
		CBVarIntEncode(data, cursor, varInt);
		cursor += varInt.size;
		for (uint32_t x = 0; x < self->outputNum; x++) {
			CBByteArraySetInt64(data, cursor, self->outputs[x]->value);
			cursor += 8;
			varInt = CBVarIntFromUInt64(CBGetByteArray(self->outputs[x]->scriptObject)->length);
			CBVarIntEncode(data, cursor, varInt);
			cursor += varInt.size;
			CBByteArrayCopyByteArray(data, cursor, CBGetByteArray(self->outputs[x]->scriptObject));
			cursor += varInt.val;
		}
	}
	// Set lockTime
	CBByteArraySetInt32(data, cursor, self->lockTime);
	CBByteArraySetInt32(data, cursor + 4, signType);
	assert(sizeOfData == cursor + 8); // Must always be like this
	uint8_t firstHash[32];
	CBSha256(CBByteArrayGetData(data), sizeOfData, firstHash);
	CBSha256(firstHash, 32, hash);
	return CB_TX_HASH_OK;
}
Exemple #15
0
bool CBAlertSerialisePayload(CBAlert * self) {
	
	CBByteArray * bytes = CBGetMessage(self)->bytes;
	if (! bytes) {
		CBLogError("Attempting to serialise a CBAlert with no bytes.");
		return false;
	}
	
	// Create varints and calculate length whilst at it.
	CBVarInt setCancelLen = CBVarIntFromUInt64(self->setCancelNum);
	CBVarInt userAgentLen = CBVarIntFromUInt64(self->userAgentNum);
	CBVarInt hiddenCommentLen = CBVarIntFromUInt64(self->hiddenComment ? self->hiddenComment->length : 0);
	CBVarInt displayedCommentLen = CBVarIntFromUInt64(self->displayedComment ? self->displayedComment->length : 0);
	CBVarInt reservedLen = CBVarIntFromUInt64(self->reserved ? self->reserved->length : 0);
	int length = 40 + setCancelLen.size + setCancelLen.val * 4 + userAgentLen.size + hiddenCommentLen.size + hiddenCommentLen.val + displayedCommentLen.size + displayedCommentLen.val + reservedLen.size + reservedLen.val;
	
	// Add user agents to length
	for (int x = 0; x < self->userAgentNum; x++)
		length += self->userAgents[x]->length + CBVarIntSizeOf(self->userAgents[x]->length);
	
	// So far length is for payload so make payload var int.
	CBVarInt payloadLen = CBVarIntFromUInt64(length);
	
	// Add the length of this var int.
	length += payloadLen.size;
	
	// Check length, with at least one byte for signature (could be 0 varint)
	if (bytes->length < length + 1) {
		CBLogError("Attempting to serialise a CBAlert with less bytes than required for the payload and a signature var int.");
		return false;
	}
	
	// Serialise the payload section.
	
	CBByteArraySetVarInt(bytes, 0, payloadLen);
	
	int cursor = payloadLen.size;
	CBByteArraySetInt32(bytes, cursor, self->version);
	cursor += 4;
	CBByteArraySetInt64(bytes, cursor, self->relayUntil);
	cursor += 8;
	CBByteArraySetInt64(bytes, cursor, self->expiration);
	cursor += 8;
	CBByteArraySetInt32(bytes, cursor, self->ID);
	cursor += 4;
	CBByteArraySetInt32(bytes, cursor, self->cancel);
	cursor += 4;
	
	// Cancel set
	CBByteArraySetVarInt(bytes, cursor, setCancelLen);
	cursor += setCancelLen.size;
	for (int x = 0; x < self->setCancelNum; x++) {
		CBByteArraySetInt32(bytes, cursor, self->setCancel[x]);
		cursor += 4;
	}
	
	CBByteArraySetInt32(bytes, cursor, self->minVer);
	cursor += 4;
	CBByteArraySetInt32(bytes, cursor, self->maxVer);
	cursor += 4;
	
	// User agent set
	CBByteArraySetVarInt(bytes, cursor, userAgentLen);
	cursor += userAgentLen.size;
	for (int x = 0; x < self->userAgentNum; x++) {
		CBVarInt aUserAgentLen = CBVarIntFromUInt64(self->userAgents[x]->length);
		CBByteArraySetVarInt(bytes, cursor, aUserAgentLen);
		cursor += aUserAgentLen.size;
		CBByteArrayCopyByteArray(bytes, cursor, self->userAgents[x]);
		CBByteArrayChangeReference(self->userAgents[x], bytes, cursor);
		cursor += aUserAgentLen.val;
	}
	
	CBByteArraySetInt32(bytes, cursor, self->priority);
	cursor += 4;
	
	// Hidden comment
	CBByteArraySetVarInt(bytes, cursor, hiddenCommentLen);
	cursor += hiddenCommentLen.size;
	if (self->hiddenComment) {
		CBByteArrayCopyByteArray(bytes, cursor, self->hiddenComment);
		CBByteArrayChangeReference(self->hiddenComment, bytes, cursor);
		cursor += hiddenCommentLen.val;
	}
	
	// Displayed comment
	CBByteArraySetVarInt(bytes, cursor, displayedCommentLen);
	cursor += displayedCommentLen.size;
	if (self->displayedComment) {
		CBByteArrayCopyByteArray(bytes, cursor, self->displayedComment);
		CBByteArrayChangeReference(self->displayedComment, bytes, cursor);
		cursor += displayedCommentLen.val;
	}
	
	// Reserved
	CBByteArraySetVarInt(bytes, cursor, reservedLen);
	cursor += reservedLen.size;
	if (self->reserved) {
		CBByteArrayCopyByteArray(bytes, cursor, self->reserved);
		CBByteArrayChangeReference(self->reserved, bytes, cursor);
		cursor += reservedLen.val;
	}
	
	self->payload = CBNewByteArraySubReference(bytes, payloadLen.size, cursor - payloadLen.size);
	
	return true;
	
}
Exemple #16
0
uint32_t CBVersionSerialise(CBVersion * self, bool force){
	CBByteArray * bytes = CBGetMessage(self)->bytes;
	if (NOT bytes) {
		CBGetMessage(self)->logError("Attempting to serialise a CBVersion with no bytes.");
		return 0;
	}
	if (bytes->length < 46) {
		CBGetMessage(self)->logError("Attempting to serialise a CBVersion with less than 46 bytes.");
		return 0;
	}
	CBByteArraySetInt32(bytes, 0, self->version);
	CBByteArraySetInt64(bytes, 4, self->services);
	CBByteArraySetInt64(bytes, 12, self->time);
	if (force && CBGetMessage(self->addRecv)->serialised)
		CBReleaseObject(CBGetMessage(self->addRecv)->bytes);
	if (NOT CBGetMessage(self->addRecv)->serialised || force) {
		CBGetMessage(self->addRecv)->bytes = CBByteArraySubReference(bytes, 20, bytes->length-20);
		if (NOT CBGetMessage(self->addRecv)->bytes) {
			CBGetMessage(self)->logError("Cannot create a new CBByteArray sub reference in CBVersionSerialise for receiving address.");
			return 0;
		}
		uint32_t len = CBNetworkAddressSerialise(self->addRecv,false);
		if (NOT len) {
			CBGetMessage(self)->logError("CBVersion cannot be serialised because of an error with the receiving CBNetworkAddress");
			// Release bytes to avoid problems overwritting pointer without release, if serialisation is tried again.
			CBReleaseObject(CBGetMessage(self->addRecv)->bytes);
			return 0;
		}
		CBGetMessage(self->addRecv)->bytes->length = len;
	}else if (CBGetMessage(self->addRecv)->bytes->sharedData != bytes->sharedData){
		// Move serialsed data to one location
		CBByteArrayCopyByteArray(bytes, 20, CBGetMessage(self->addRecv)->bytes);
		CBByteArrayChangeReference(CBGetMessage(self->addRecv)->bytes, bytes, 20);
	}
	if (self->version >= 106) {
		if (bytes->length < 85) {
			CBGetMessage(self)->logError("Attempting to serialise a CBVersion with less than 85 bytes required.");
			return 0;
		}
		if (self->userAgent->length > 400) {
			CBGetMessage(self)->logError("Attempting to serialise a CBVersion with a userAgent over 400 bytes.");
			return 0;
		}
		if (force && CBGetMessage(self->addSource)->serialised)
			CBReleaseObject(CBGetMessage(self->addSource)->bytes);
		if (NOT CBGetMessage(self->addSource)->serialised || force) {
			CBGetMessage(self->addSource)->bytes = CBByteArraySubReference(bytes, 46, bytes->length-46);
			if (NOT CBGetMessage(self->addSource)->bytes) {
				CBGetMessage(self)->logError("Cannot create a new CBByteArray sub reference in CBVersionSerialise for source address.");
				return 0;
			}
			uint32_t len = CBNetworkAddressSerialise(self->addSource,false);
			if (NOT len) {
				CBGetMessage(self)->logError("CBVersion cannot be serialised because of an error with the source CBNetworkAddress");
				// Release bytes to avoid problems overwritting pointer without release, if serialisation is tried again.
				CBReleaseObject(CBGetMessage(self->addSource)->bytes);
				return 0;
			}
			CBGetMessage(self->addSource)->bytes->length = len;
		}else if (CBGetMessage(self->addSource)->bytes->sharedData != bytes->sharedData){
			// Move serialsed data to one location
			CBByteArrayCopyByteArray(bytes, 46, CBGetMessage(self->addSource)->bytes);
			CBByteArrayChangeReference(CBGetMessage(self->addSource)->bytes, bytes, 46);
		}
		CBByteArraySetInt64(bytes, 72, self->nonce);
		CBVarInt varInt = CBVarIntFromUInt64(self->userAgent->length);
		CBVarIntEncode(bytes, 80, varInt);
		if (bytes->length < 84 + varInt.size + varInt.val) {
			CBGetMessage(self)->logError("Attempting to deserialise a CBVersion without enough space to cover the userAgent and block height.");
			return 0;
		}
		CBByteArrayCopyByteArray(bytes, 80 + varInt.size,self->userAgent);
		CBByteArrayChangeReference(self->userAgent,bytes,80 + varInt.size);
		CBByteArraySetInt32(bytes, 80 + varInt.size + (uint32_t)varInt.val, self->blockHeight);
		CBGetMessage(self)->serialised = true;
		return 84 + varInt.size + (uint32_t)varInt.val;
	}else{
		// Not the further message.
		CBGetMessage(self)->serialised = true;
		return 46;
	}
}
Exemple #17
0
uint32_t CBBlockSerialise(CBBlock * self, bool transactions, bool force){
	CBByteArray * bytes = CBGetMessage(self)->bytes;
	if (NOT bytes) {
		CBLogError("Attempting to serialise a CBBlock with no bytes.");
		return 0;
	}
	CBVarInt transactionNum = CBVarIntFromUInt64(self->transactionNum);
	uint32_t cursor = 80 + transactionNum.size;
	if (bytes->length < cursor + 1) {
		CBLogError("Attempting to serialise a CBBlock with less bytes than required for the header, transaction number var int and at least a null byte. %i < %i", bytes->length, cursor + 1);
		return 0;
	}
	// Do header
	CBByteArraySetInt32(bytes, 0, self->version);
	CBByteArrayCopyByteArray(bytes, 4, self->prevBlockHash);
	CBByteArrayChangeReference(self->prevBlockHash, bytes, 4);
	CBByteArrayCopyByteArray(bytes, 36, self->merkleRoot);
	CBByteArrayChangeReference(self->merkleRoot, bytes, 36);
	CBByteArraySetInt32(bytes, 68, self->time);
	CBByteArraySetInt32(bytes, 72, self->target);
	CBByteArraySetInt32(bytes, 76, self->nonce);
	// Do Transactions
	CBVarIntEncode(bytes, 80, transactionNum);
	if (transactions) {
		for (uint32_t x = 0; x < self->transactionNum; x++) {
			if (NOT CBGetMessage(self->transactions[x])->serialised // Serailise if not serialised yet.
				// Serialise if force is true.
				|| force
				// If the data shares the same data as this block, re-serialise the transaction, in case it got overwritten.
				|| CBGetMessage(self->transactions[x])->bytes->sharedData == bytes->sharedData) {
				if (CBGetMessage(self->transactions[x])->serialised)
					// Release old byte array
					CBReleaseObject(CBGetMessage(self->transactions[x])->bytes);
				CBGetMessage(self->transactions[x])->bytes = CBByteArraySubReference(bytes, cursor, bytes->length-cursor);
				if (NOT CBGetMessage(self->transactions[x])->bytes) {
					CBLogError("Cannot create a new CBByteArray sub reference in CBBlockSerialise for the transaction number %u", x);
					return 0;
				}
				if (NOT CBTransactionSerialise(self->transactions[x], force)) {
					CBLogError("CBBlock cannot be serialised because of an error with the transaction number %u.", x);
					return 0;
				}
			}else{
				// Move serialsed data to one location
				if (bytes->length < cursor + CBGetMessage(self->transactions[x])->bytes->length) {
					CBLogError("CBBlock cannot be serialised because there was not enough bytes for the transaction number %u (%u < %u).", x, bytes->length, cursor + CBGetMessage(self->transactions[x])->bytes->length);
					return 0;
				}
				CBByteArrayCopyByteArray(bytes, cursor, CBGetMessage(self->transactions[x])->bytes);
				CBByteArrayChangeReference(CBGetMessage(self->transactions[x])->bytes, bytes, cursor);
			}
			cursor += CBGetMessage(self->transactions[x])->bytes->length;
		}
	}else{
		// Add null byte since there are to be no transactions (header only).
		CBByteArraySetByte(bytes, cursor, 0);
		cursor++;
	}
	// Reset hash
	self->hashSet = false;
	// Ensure data length is correct.
	bytes->length = cursor;
	// Is now serialised.
	CBGetMessage(self)->serialised = true;
	return cursor;
}