예제 #1
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;
}
예제 #2
0
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;
}
예제 #3
0
uint32_t CBInventoryBroadcastSerialise(CBInventoryBroadcast * self){
	CBByteArray * bytes = CBGetMessage(self)->bytes;
	if (NOT bytes) {
		CBGetMessage(self)->events->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)->events->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++) {
		CBGetMessage(self->items[x])->bytes = CBByteArraySubReference(bytes, cursor, bytes->length-cursor);
		uint32_t len = CBInventoryItemSerialise(self->items[x]);
		if (NOT len) {
			CBGetMessage(self)->events->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;
		cursor += len;
	}
	return cursor;
}
예제 #4
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;
}
예제 #5
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;
}
예제 #6
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;
}
예제 #7
0
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;
}
예제 #8
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;
}
예제 #9
0
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;
}
예제 #10
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;
}
예제 #11
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;
}
예제 #12
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;
	}
}
예제 #13
0
파일: CBBlock.c 프로젝트: GMD1987/cbitcoin
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;
}