Ejemplo n.º 1
0
int main(){
	unsigned int s = (unsigned int)time(NULL);
	s = 1337544566;
	printf("Session = %ui\n",s);
	srand(s);
	FILE * f = fopen("scriptCases.txt", "r");
	if (!f) printf("FILE WONT OPEN\n");
	for (uint16_t x = 0;;) {
		char * line = NULL;
		uint16_t lineLen = 0;
		bool eof = false;
		while (true) {
			line = realloc(line, lineLen + 101);
			if(!fgets(line + lineLen, 101, f)){
				eof = true;
				break;
			}
			if (line[strlen(line)-1] == '\n') break; // Got to the end of the line
			lineLen += 100;
		}
		if(eof) break;
		line[strlen(line)-1] = '\0';
		if (!(line[0] == '/' && line[1] == '/') && strlen(line)){
			x++;
			CBScript * script = CBNewScriptFromString(line, logError);
			if (!script) {
				printf("%i: {%s} INVALID\n",x,line);
				return 1;
			}else{
				CBScriptStack stack = CBNewEmptyScriptStack();
				if (x == 31) {
					printf("");
				}
				bool res = CBScriptExecute(script, &stack, NULL, NULL, 0, true);
				CBFreeScriptStack(stack);
				if (res != ((fgetc(f) == '1') ? CB_SCRIPT_VALID : CB_SCRIPT_INVALID)) {
					printf("%i: {%s} FAIL\n",x,line);
					return 1;
				}else{
					printf("%i: {%s} OK\n",x,line);
				}
				CBReleaseObject(script);
				fseek(f, 1, SEEK_CUR);
			}
		}
		free(line);
	}
	fclose(f);
	// Test PUSHDATA
	CBScript * script = CBNewScriptWithDataCopy((uint8_t []){CB_SCRIPT_OP_PUSHDATA1,0x01,0x47,CB_SCRIPT_OP_DUP,CB_SCRIPT_OP_PUSHDATA2,0x01,0x00,0x47,CB_SCRIPT_OP_EQUALVERIFY,CB_SCRIPT_OP_PUSHDATA4,0x01,0x00,0x00,0x00,0x47,CB_SCRIPT_OP_EQUAL}, 16, logError);
	CBScriptStack stack = CBNewEmptyScriptStack();
	if(CBScriptExecute(script, &stack, NULL, NULL, 0, true) != CB_SCRIPT_VALID){
		printf("PUSHDATA TEST 1 FAIL\n");
		return 1;
	}
	CBReleaseObject(script);
	script = CBNewScriptWithDataCopy((uint8_t []){CB_SCRIPT_OP_PUSHDATA1,0x01,0x00,CB_SCRIPT_OP_DUP,CB_SCRIPT_OP_PUSHDATA2,0x01,0x00,0x00,CB_SCRIPT_OP_EQUALVERIFY,CB_SCRIPT_OP_PUSHDATA4,0x01,0x00,0x00,0x00,0x00,CB_SCRIPT_OP_EQUAL}, 16, logError);
	stack = CBNewEmptyScriptStack();
	if(CBScriptExecute(script, &stack, NULL, NULL, 0, true) != CB_SCRIPT_VALID){
		printf("PUSHDATA TEST 2 FAIL\n");
		return 1;
	}
	CBReleaseObject(script);
	// Test stack length limit
	script = CBNewScriptWithDataCopy((uint8_t []){CB_SCRIPT_OP_TRUE}, 1, logError);
	stack = CBNewEmptyScriptStack();
	for (int x = 0; x < 1001; x++)
		CBScriptStackPushItem(&stack, (CBScriptStackItem){NULL,0});
	if(CBScriptExecute(script, &stack, NULL, NULL, 0, true) != CB_SCRIPT_INVALID){
		printf("STACK LIMIT TEST FAIL\n");
		return 1;
	}
	CBReleaseObject(script);
	// Test P2SH
	CBScript * inputScript = CBNewScriptWithDataCopy((uint8_t []){CB_SCRIPT_OP_14,0x04,CB_SCRIPT_OP_5,CB_SCRIPT_OP_9,CB_SCRIPT_OP_ADD,CB_SCRIPT_OP_EQUAL}, 6, logError);
	CBScript * outputScript = CBNewScriptWithDataCopy((uint8_t []){CB_SCRIPT_OP_HASH160,0x14,0x87,0xF3,0xB6,0x21,0xF1,0x8C,0x50,0x06,0x8B,0x7D,0xAB,0xA1,0x60,0xBB,0x2C,0x51,0xFD,0xD6,0xA5,0xE2,CB_SCRIPT_OP_EQUAL}, 23, logError);
	stack = CBNewEmptyScriptStack();
	CBScriptExecute(inputScript, &stack, NULL, NULL, 0, false);
	if (CBScriptExecute(outputScript, &stack, NULL, NULL, 0, false) != CB_SCRIPT_VALID) {
		printf("OK NO PS2H FAIL\n");
		return 1;
	}
	stack = CBNewEmptyScriptStack();
	CBScriptExecute(inputScript, &stack, NULL, NULL, 0, false);
	if (CBScriptExecute(outputScript, &stack, NULL, NULL, 0, true) != CB_SCRIPT_VALID) {
		printf("OK YES PS2H FAIL\n");
		return 1;
	}
	CBByteArraySetByte(inputScript, 0, CB_SCRIPT_OP_13);
	stack = CBNewEmptyScriptStack();
	CBScriptExecute(inputScript, &stack, NULL, NULL, 0, false);
	if (CBScriptExecute(outputScript, &stack, NULL, NULL, 0, false) != CB_SCRIPT_VALID) {
		printf("BAD NO PS2H FAIL\n");
		return 1;
	}
	stack = CBNewEmptyScriptStack();
	CBScriptExecute(inputScript, &stack, NULL, NULL, 0, false);
	CBReleaseObject(inputScript);
	if (CBScriptExecute(outputScript, &stack, NULL, NULL, 0, true) != CB_SCRIPT_INVALID) {
		printf("BAD YES PS2H FAIL\n");
		return 1;
	}
	CBFreeScriptStack(stack);
	CBReleaseObject(outputScript);
	// Test CBScriptIsPushOnly
	script = CBNewScriptWithDataCopy((uint8_t [20]){0x02,0x04,0x73,CB_SCRIPT_OP_PUSHDATA1,0x03,0xA2,0x70,0x73,CB_SCRIPT_OP_PUSHDATA2,0x01,0x00,0x5A,CB_SCRIPT_OP_PUSHDATA4,0x03,0x0,0x0,0x0,0x5F,0x70,0x74}, 20, &logError);
	if (NOT CBScriptIsPushOnly(script)) {
		printf("IS PUSH PUSH FAIL\n");
		return 1;
	}
	CBReleaseObject(script);
	script = CBNewScriptWithDataCopy((uint8_t [13]){0x02,0x04,0x73,CB_SCRIPT_OP_PUSHDATA1,0x03,0xA2,0x70,0x73,CB_SCRIPT_OP_PUSHDATA2,0x01,0x00,0x5A,CB_SCRIPT_OP_0}, 13, &logError);
	if (CBScriptIsPushOnly(script)) {
		printf("IS PUSH ZERO FAIL\n");
		return 1;
	}
	CBReleaseObject(script);
	script = CBNewScriptWithDataCopy((uint8_t [12]){0x02,0x04,0x73,CB_SCRIPT_OP_1,0x03,0xA2,0x70,0x73,CB_SCRIPT_OP_PUSHDATA2,0x01,0x00,0x5A}, 12, &logError);
	if (CBScriptIsPushOnly(script)) {
		printf("IS PUSH ONE FAIL\n");
		return 1;
	}
	CBReleaseObject(script);
	return 0;
}
Ejemplo n.º 2
0
void CBFreeVersionChecksumBytes(void * vself){
	CBVersionChecksumBytes * self = vself;
	if (self->cachedString) CBReleaseObject(self->cachedString);
	CBFreeByteArray(CBGetByteArray(self));
}
Ejemplo n.º 3
0
void CBFreeTransactionInput(void * vself){
	CBTransactionInput * self = vself;
	if (self->scriptObject) CBReleaseObject(self->scriptObject);
	if (self->prevOut.hash) CBReleaseObject(self->prevOut.hash);
	CBFreeMessage(self);
}
Ejemplo n.º 4
0
CBOnMessageReceivedAction CBNodeReturnError(CBNode * self, char * err){
	CBLogError(err);
	self->callbacks.onFatalNodeError(self, CB_ERROR_GENERAL);
	CBReleaseObject(self);
	return CB_MESSAGE_ACTION_CONTINUE;
}
Ejemplo n.º 5
0
int main(){
	unsigned int s = (unsigned int)time(NULL);
	s = 1337544566;
	printf("Session = %ui\n",s);
	srand(s);
	// Test genesis block
	CBByteArray * genesisMerkleRoot = CBNewByteArrayWithDataCopy((uint8_t []){0x3B,0xA3,0xED,0xFD,0x7A,0x7B,0x12,0xB2,0x7A,0xC7,0x2C,0x3E,0x67,0x76,0x8F,0x61,0x7F,0xC8,0x1B,0xC3,0x88,0x8A,0x51,0x32,0x3A,0x9F,0xB8,0xAA,0x4B,0x1E,0x5E,0x4A}, 32, onErrorReceived);
	CBByteArray * genesisInScript = CBNewByteArrayWithDataCopy((uint8_t [77]){0x04,0xFF,0xFF,0x00,0x1D,0x01,0x04,0x45,0x54,0x68,0x65,0x20,0x54,0x69,0x6D,0x65,0x73,0x20,0x30,0x33,0x2F,0x4A,0x61,0x6E,0x2F,0x32,0x30,0x30,0x39,0x20,0x43,0x68,0x61,0x6E,0x63,0x65,0x6C,0x6C,0x6F,0x72,0x20,0x6F,0x6E,0x20,0x62,0x72,0x69,0x6E,0x6B,0x20,0x6F,0x66,0x20,0x73,0x65,0x63,0x6F,0x6E,0x64,0x20,0x62,0x61,0x69,0x6C,0x6F,0x75,0x74,0x20,0x66,0x6F,0x72,0x20,0x62,0x61,0x6E,0x6B,0x73}, 77, onErrorReceived);
	CBByteArray * genesisOutScript = CBNewByteArrayWithDataCopy((uint8_t [67]){0x41,0x04,0x67,0x8A,0xFD,0xB0,0xFE,0x55,0x48,0x27,0x19,0x67,0xF1,0xA6,0x71,0x30,0xB7,0x10,0x5C,0xD6,0xA8,0x28,0xE0,0x39,0x09,0xA6,0x79,0x62,0xE0,0xEA,0x1F,0x61,0xDE,0xB6,0x49,0xF6,0xBC,0x3F,0x4C,0xEF,0x38,0xC4,0xF3,0x55,0x04,0xE5,0x1E,0xC1,0x12,0xDE,0x5C,0x38,0x4D,0xF7,0xBA,0x0B,0x8D,0x57,0x8A,0x4C,0x70,0x2B,0x6B,0xF1,0x1D,0x5F,0xAC}, 67, onErrorReceived);
	// Test hash
	CBBlock * genesisBlock = CBNewBlockGenesis(onErrorReceived);
	uint8_t calcHash[32];
	CBBlockCalculateHash(genesisBlock,calcHash);
	if(memcmp(genesisBlock->hash, calcHash,32)){
		printf("GENESIS BLOCK HASH FAIL\n0x");
		uint8_t * d = genesisBlock->hash;
		for (int x = 0; x < 32; x++) {
			printf("%.2X",d[x]);
		}
		printf("\n!=\n0x");
		d = calcHash;
		for (int x = 0; x < 32; x++) {
			printf("%.2X",d[x]);
		}
		return 1;
	}
	// Test deserialised data
	if (genesisBlock->version != 1) {
		printf("GENESIS BLOCK VERSION FAIL\n");
		return 1;
	}
	for (int x = 0; x < 32; x++) {
		if(CBByteArrayGetByte(genesisBlock->prevBlockHash, x) != 0){
			printf("GENESIS BLOCK PREV FAIL\n");
			return 1;
		}
	}
	if (CBByteArrayCompare(genesisBlock->merkleRoot, genesisMerkleRoot)) {
		printf("GENESIS BLOCK MERKLE ROOT FAIL\n0x");
		uint8_t * d = CBByteArrayGetData(genesisBlock->merkleRoot);
		for (int x = 0; x < 32; x++) {
			printf("%.2X",d[x]);
		}
		printf("\n!=\n0x");
		d = CBByteArrayGetData(genesisMerkleRoot);
		for (int x = 0; x < 32; x++) {
			printf("%.2X",d[x]);
		}
		return 1;
	}
	if (genesisBlock->time != 1231006505) {
		printf("GENESIS BLOCK TIME FAIL\n0x");
		return 1;
	}
	if (genesisBlock->target != 0x1D00FFFF) {
		printf("GENESIS BLOCK DIFFICULTY FAIL\n0x");
		return 1;
	}
	if (genesisBlock->nonce != 2083236893) {
		printf("GENESIS BLOCK DIFFICULTY FAIL\n0x");
		return 1;
	}
	if (genesisBlock->transactionNum != 1) {
		printf("GENESIS BLOCK TRANSACTION NUM FAIL\n0x");
		return 1;
	}
	CBTransaction * genesisCoinBase = genesisBlock->transactions[0];
	if (genesisCoinBase->inputNum != 1) {
		printf("GENESIS BLOCK TRANSACTION INPUT NUM FAIL\n0x");
		return 1;
	}
	if (genesisCoinBase->outputNum != 1) {
		printf("GENESIS BLOCK TRANSACTION OUTPUT NUM FAIL\n0x");
		return 1;
	}
	if (genesisCoinBase->version != 1) {
		printf("GENESIS BLOCK TRANSACTION VERSION FAIL\n0x");
		return 1;
	}
	if (genesisCoinBase->lockTime != 0) {
		printf("GENESIS BLOCK TRANSACTION LOCK TIME FAIL\n0x");
		return 1;
	}
	if (genesisCoinBase->inputs[0]->scriptObject->length != 0x4D) {
		printf("GENESIS BLOCK TRANSACTION INPUT SCRIPT LENGTH FAIL\n0x");
		return 1;
	}
	if (genesisCoinBase->outputs[0]->scriptObject->length != 0x43) {
		printf("GENESIS BLOCK TRANSACTION OUTPUT SCRIPT LENGTH FAIL\n0x");
		return 1;
	}
	for (int x = 0; x < 32; x++) {
		if(CBByteArrayGetByte(genesisCoinBase->inputs[0]->prevOut.hash, x) != 0){
			printf("GENESIS BLOCK TRANSACTION INPUT OUT POINTER HASH FAIL\n");
			return 1;
		}
	}
	if (genesisCoinBase->inputs[0]->prevOut.index != 0xFFFFFFFF) {
		printf("GENESIS BLOCK TRANSACTION INPUT OUT POINTER INDEX FAIL\n0x");
		return 1;
	}
	if (genesisCoinBase->inputs[0]->sequence != CB_TRANSACTION_INPUT_FINAL) {
		printf("GENESIS BLOCK TRANSACTION INPUT SEQUENCE FAIL\n0x");
		return 1;
	}
	if (CBByteArrayCompare(genesisCoinBase->inputs[0]->scriptObject, genesisInScript)) {
		printf("GENESIS BLOCK IN SCRIPT FAIL\n0x");
		uint8_t * d = CBByteArrayGetData(genesisCoinBase->inputs[0]->scriptObject);
		for (int x = 0; x < genesisCoinBase->inputs[0]->scriptObject->length; x++) {
			printf("%.2X",d[x]);
		}
		printf("\n!=\n0x");
		d = CBByteArrayGetData(genesisInScript);
		for (int x = 0; x < genesisInScript->length; x++) {
			printf("%.2X",d[x]);
		}
		return 1;
	}
	if (genesisCoinBase->outputs[0]->value != 5000000000) {
		printf("GENESIS BLOCK TRANSACTION OUTPUT VALUE FAIL\n0x");
		return 1;
	}
	if (CBByteArrayCompare(genesisCoinBase->outputs[0]->scriptObject, genesisOutScript)) {
		printf("GENESIS BLOCK OUT SCRIPT FAIL\n0x");
		uint8_t * d = CBByteArrayGetData(genesisCoinBase->outputs[0]->scriptObject);
		for (int x = 0; x < genesisCoinBase->outputs[0]->scriptObject->length; x++) {
			printf("%.2X",d[x]);
		}
		printf("\n!=\n0x");
		d = CBByteArrayGetData(genesisOutScript);
		for (int x = 0; x < genesisOutScript->length; x++) {
			printf("%.2X",d[x]);
		}
		return 1;
	}
	// Test serialisation into genesis block
	CBBlock * block = CBNewBlock(onErrorReceived);
	block->version = 1;
	uint8_t * zeroHash = malloc(32);
	memset(zeroHash, 0, 32);
	block->prevBlockHash = CBNewByteArrayWithData(zeroHash, 32, onErrorReceived);
	block->merkleRoot = genesisMerkleRoot;
	block->target = 0x1D00FFFF;
	block->time = 1231006505;
	block->nonce = 2083236893;
	block->transactionNum = 1;
	block->transactions = malloc(sizeof(*block->transactions));
	block->transactions[0] = CBNewTransaction(0, 1, onErrorReceived);
	CBRetainObject(block->prevBlockHash); // Retain for the zero hash in the input
	CBTransactionTakeInput(block->transactions[0], CBNewTransactionInput(genesisInScript, CB_TRANSACTION_INPUT_FINAL, block->prevBlockHash, 0xFFFFFFFF, onErrorReceived));
	CBTransactionTakeOutput(block->transactions[0], CBNewTransactionOutput(5000000000, genesisOutScript, onErrorReceived));
	CBGetMessage(block)->bytes = CBNewByteArrayOfSize(CBGetMessage(genesisBlock)->bytes->length, onErrorReceived);
	CBBlockSerialise(block, true, true);
	if (CBByteArrayCompare(CBGetMessage(block)->bytes, CBGetMessage(genesisBlock)->bytes)) {
		printf("SERIALISATION TO GENESIS BLOCK FAIL\n0x");
		uint8_t * d = CBByteArrayGetData(CBGetMessage(block)->bytes);
		for (int x = 0; x < CBGetMessage(block)->bytes->length; x++) {
			printf("%.2X",d[x]);
		}
		printf("\n!=\n0x");
		d = CBByteArrayGetData(CBGetMessage(genesisBlock)->bytes);
		for (int x = 0; x < CBGetMessage(genesisBlock)->bytes->length; x++) {
			printf("%.2X",d[x]);
		}
		return 1;
	}
	CBReleaseObject(genesisBlock);
	// ??? Add tests for non-genesis blocks
	return 0;
}
Ejemplo n.º 6
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;
}
Ejemplo n.º 7
0
uint32_t CBVersionDeserialise(CBVersion * self){
	CBByteArray * bytes = CBGetMessage(self)->bytes;
	if (NOT bytes) {
		CBGetMessage(self)->logError("Attempting to deserialise a CBVersion with no bytes.");
		return 0;
	}
	if (bytes->length < 46) {
		CBGetMessage(self)->logError("Attempting to deserialise a CBVersion with less than 46 bytes.");
		return 0;
	}
	self->version = CBByteArrayReadInt32(bytes, 0);
	self->services = (CBVersionServices) CBByteArrayReadInt64(bytes, 4);
	self->time = CBByteArrayReadInt64(bytes, 12);
	CBByteArray * data = CBByteArraySubReference(bytes, 20, bytes->length-20); // Get data from 20 bytes to the end of the byte array to deserialise the recieving network address.
	if (NOT data) {
		CBGetMessage(self)->logError("Cannot create a new CBByteArray in CBVersionDeserialise for the receiving address.");
		return 0;
	}
	self->addRecv = CBNewNetworkAddressFromData(data, CBGetMessage(self)->logError);
	if (NOT self->addRecv) {
		CBGetMessage(self)->logError("Cannot create a new CBNetworkAddress in CBVersionDeserialise for the receiving address.");
		CBReleaseObject(data);
		return 0;
	}
	uint32_t len = CBNetworkAddressDeserialise(self->addRecv, false); // No time from version message.
	if (NOT len){
		CBGetMessage(self)->logError("CBVersion cannot be deserialised because of an error with the receiving address.");
		CBReleaseObject(data);
		return 0;
	}
	// Readjust CBByteArray length for recieving address
	data->length = len;
	CBReleaseObject(data);
	if (self->version >= 106) { // ??? Very old. No need for backwards compatibility? Might as well.
		if (bytes->length < 85) {
			CBGetMessage(self)->logError("Attempting to deserialise a CBVersion with less than 85 bytes required.");
			return 0;
		}
		// Source address deserialisation
		data = CBByteArraySubReference(bytes, 46, bytes->length-46);
		if (NOT data) {
			CBGetMessage(self)->logError("Cannot create a new CBByteArray in CBVersionDeserialise for the source address.");
			return 0;
		}
		self->addSource = CBNewNetworkAddressFromData(data, CBGetMessage(self)->logError);
		if (NOT self->addSource) {
			CBGetMessage(self)->logError("Cannot create a new CBNetworkAddress in CBVersionDeserialise for the source address.");
			CBReleaseObject(data);
			return 0;
		}
		uint32_t len = CBNetworkAddressDeserialise(self->addSource, false); // No time from version message.
		if (NOT len){
			CBGetMessage(self)->logError("CBVersion cannot be deserialised because of an error with the source address.");
			CBReleaseObject(data);
			return 0;
		}
		// Readjust CBByteArray length for source address
		data->length = len;
		CBReleaseObject(data);
		self->nonce = CBByteArrayReadInt64(bytes, 72);
		uint8_t x = CBByteArrayGetByte(bytes, 80); // Check length for decoding CBVarInt
		if (x > 253){
			CBGetMessage(self)->logError("Attempting to deserialise a CBVersion with a var string that is too big.");
			return 0;
		}
		CBVarInt varInt = CBVarIntDecode(bytes, 80);
		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;
		}
		if (varInt.val > 400) { // cbitcoin accepts userAgents upto 400 bytes
			CBGetMessage(self)->logError("Attempting to deserialise a CBVersion with a userAgent over 400 bytes.");
			return 0;
		}
		self->userAgent = CBNewByteArraySubReference(bytes, 80 + varInt.size, (uint32_t)varInt.val);
		if (NOT self->userAgent) {
			CBGetMessage(self)->logError("Cannot create a new CBByteArray in CBVersionDeserialise");
			return 0;
		}
		self->blockHeight = CBByteArrayReadInt32(bytes, 80 + varInt.size + (uint32_t)varInt.val);
		return 84 + varInt.size + (uint32_t)varInt.val;
	}else return 46; // Not the further message.
}
Ejemplo n.º 8
0
uint32_t CBBlockDeserialise(CBBlock * self, bool transactions){
	CBByteArray * bytes = CBGetMessage(self)->bytes;
	if (NOT bytes) {
		CBLogError("Attempting to deserialise a CBBlock with no bytes.");
		return 0;
	}
	if (bytes->length < 82) {
		CBLogError("Attempting to deserialise a CBBlock with less than 82 bytes. Minimum for header (With null byte).");
		return 0;
	}
	self->version = CBByteArrayReadInt32(bytes, 0);
	self->prevBlockHash = CBByteArraySubReference(bytes, 4, 32);
	if (NOT self->prevBlockHash){
		CBLogError("Cannot create the previous block hash CBByteArray in CBBlockDeserialise.");
		return 0;
	}
	self->merkleRoot = CBByteArraySubReference(bytes, 36, 32);
	if (NOT self->merkleRoot){
		CBLogError("Cannot create the merkle root CBByteArray in CBBlockDeserialise.");
		return 0;
	}
	self->time = CBByteArrayReadInt32(bytes, 68);
	self->target = CBByteArrayReadInt32(bytes, 72);
	self->nonce = CBByteArrayReadInt32(bytes, 76);
	// If first VarInt byte is zero, then stop here for headers, otherwise look for 8 more bytes and continue
	uint8_t firstByte = CBByteArrayGetByte(bytes, 80);
	if (transactions && firstByte) {
		// More to come
		if (bytes->length < 89) {
			CBLogError("Attempting to deserialise a CBBlock with a non-zero varint with less than 89 bytes.");
			return 0;
		}
		CBVarInt transactionNumVarInt = CBVarIntDecode(bytes, 80);
		if (transactionNumVarInt.val*60 > bytes->length - 81) {
			CBLogError("Attempting to deserialise a CBBlock with too many transactions for the byte data length.");
			return 0;
		}
		self->transactionNum = (uint32_t)transactionNumVarInt.val;
		self->transactions = malloc(sizeof(*self->transactions) * self->transactionNum);
		if (NOT self->transactionNum) {
			CBLogError("Cannot allocate %i bytes of memory in CBBlockDeserialise\n", sizeof(*self->transactions) * self->transactionNum);
			return 0;
		}
		uint32_t cursor = 80 + transactionNumVarInt.size;
		for (uint16_t x = 0; x < self->transactionNum; x++) {
			CBByteArray * data = CBByteArraySubReference(bytes, cursor, bytes->length-cursor);
			if (NOT data) {
				CBLogError("Could not create a new CBByteArray in CBBlockDeserialise for the transaction number %u.", x);
			}
			CBTransaction * transaction = CBNewTransactionFromData(data);
			if (NOT transaction){
				CBLogError("Could not create a new CBTransaction in CBBlockDeserialise for the transaction number %u.", x);
				CBReleaseObject(data);
				return 0;
			}
			uint32_t len = CBTransactionDeserialise(transaction);
			if (NOT len){
				CBLogError("CBBlock cannot be deserialised because of an error with the transaction number %u.", x);
				CBReleaseObject(data);
				return 0;
			}
			// Read just the CBByteArray length
			data->length = len;
			CBReleaseObject(data);
			self->transactions[x] = transaction;
			cursor += len;
		}
		return cursor;
	}else{ // Just header
		uint8_t x;
		if (firstByte < 253) {
			x = 1;
		}else if (firstByte == 253){
			x = 2;
		}else if (firstByte == 254){
			x = 4;
		}else{
			x = 8;
		}
		if (bytes->length < 80 + x + 1) {
			CBLogError("Attempting to deserialise a CBBlock header with not enough space to cover the var int.");
			return 0;
		}
		self->transactionNum = (uint32_t)CBVarIntDecode(bytes, 80).val; // This value is undefined in the protocol. Should best be zero when getting the headers since there is not supposed to be any transactions. Would have probably been better if the var int was dropped completely for headers only.
		// Ensure null byte is null. This null byte is a bit of a nuissance but it exists in the protocol when there are no transactions.
		if (CBByteArrayGetByte(bytes, 80 + x) != 0) {
			CBLogError("Attempting to deserialise a CBBlock header with a final byte which is not null. This is not what it is supposed to be but you already knew that right?");
			return 0;
		}
		return 80 + x + 1; // 80 header bytes, the var int and the null byte
	}
}
Ejemplo n.º 9
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;
}
Ejemplo n.º 10
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;
	
}
Ejemplo n.º 11
0
int 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);
	CBByteArraySetVarInt(bytes, 0, num);
	int cursor = num.size;
	
	for (int 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 (! CBBlockSerialise(self->blockHeaders[x], false, force)) { // false for no transactions.
				
				CBLogError("CBBlockHeaders cannot be serialised because of an error with the CBBlock number %" PRIu16 ".", x);
				
				// Release CBByteArray objects to avoid problems overwritting pointer without release, if serialisation is tried again.
				for (int 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;
	
}
Ejemplo n.º 12
0
/*  socket_fd < 0 implies we need to use non-blocking connect
 * socket_fd >= 0 implies socket already bound to connection */
BRConnection *BRNewConnection(char *ip, uint16_t port,
        CBNetworkAddress *my_address, void *connector, int socket_fd) {
    int rtn;
    struct sockaddr_in remote;
    BRConnection *c = calloc(1, sizeof(BRConnection));
    if (c == NULL) {
        perror("calloc failed");
        exit(1);
    }

    if (socket_fd >= 0) {
        c->sock = socket_fd;
        c->flags = fcntl(c->sock, F_GETFL);
    } else {
        c->sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
        if (c->sock < 0) {
            perror("socket failed");
            exit(1);
        }
        /* set to non-blocking, saving flags */
        c->flags = fcntl(c->sock, F_GETFL);
        if (fcntl(c->sock, F_SETFL, c->flags | O_NONBLOCK) == -1) {
            perror("fcntl failed");
            exit(1);
        }

        memset(&remote, 0, sizeof(remote));
        remote.sin_family = AF_INET;
        rtn = inet_pton(AF_INET, ip, &remote.sin_addr.s_addr);
        if (rtn == 0)
            fprintf(stderr, "Address %s not valid\n", ip);
        else if (rtn < 0) {
            perror("inet_pton failed");
            exit(1);
        }
        remote.sin_port = htons(port);
        
        if (connect(c->sock, (struct sockaddr *) &remote,
                    sizeof(remote)) < 0) {
            if (errno == EINPROGRESS) {
#ifdef BRDEBUG
                printf("Connection to %s:%d on socket %d in progress\n", ip, port, c->sock);
#endif
            } else {
                perror("connect failed");
                exit(1);
            }
        }
    }

    if (ip != NULL) {
        uint64_t last_seen = time(NULL);
        /* use IPv4 mapped IPv6 addresses as in https://en.bitcoin.it/wiki/Protocol_Specification#Network_address */
        struct in_addr addr;
        inet_aton(ip, &addr);
        uint8_t *octets = (uint8_t *) &addr.s_addr;
        uint8_t ipmap[16] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xFF, 0xFF,
                            octets[0], octets[1], octets[2], octets[3]};
        CBByteArray *ip_arr = CBNewByteArrayWithDataCopy(ipmap, 16);
        CBVersionServices services = CB_SERVICE_FULL_BLOCKS;
        bool is_public = true;

        printf("port: %d\n", port);
        c->address = CBNewNetworkAddress(last_seen,
                                        ip_arr, port, services, is_public);
        c->my_address = my_address;

        /* decrement reference counter */
        CBReleaseObject(ip_arr);

        /* copy ip and port */
        c->port = port;
        c->ip = calloc(1, strlen(ip) + 1);
        if (c->ip == NULL) {
            perror("calloc failed");
            exit(1);
        }
        strcpy(c->ip, ip);
    }

    c->ver_acked = c->ver_received = 0;
    c->addr_sent = c->getblocks_sent = 0;
    c->connector = connector; /* In reality is a (BRConnector *) */
    return c;
}
Ejemplo n.º 13
0
void BRPeerCallback(void *arg) {
    /* adapted from pingpong.c example */
    BRConnection *c = (BRConnection *) arg;
    char header[24];

    int bytes = recv(c->sock, header, 24, 0), n;
    if (bytes < 0) {
        perror("recv failed");
        exit(1);
    } else if (bytes == 0) {
        fprintf(stderr, "Connection closed on socket %d\n", c->sock);
        BRCloseConnection(c);
        return;
    } else if (bytes != 24) {
        fprintf(stderr, "Read %d bytes, not 24\n", bytes);
        exit(1);
    }

    /* check magic */
    uint32_t magic = *(uint32_t *)(header + CB_MESSAGE_HEADER_NETWORK_ID);
    if (magic != NETMAGIC) {
        fprintf(stderr, "Netmagic %u incorrect (isn't %u)\n", magic, NETMAGIC);
        exit(1);
    }

    /* read message */
    uint32_t length = *(uint32_t *)(header + CB_MESSAGE_HEADER_LENGTH);
    char *message = malloc(length);
    if (message == NULL) {
        perror("malloc failed");
        exit(1);
    }
    bytes = 0;
    while (bytes < length) {
        /* TODO don't read message all at once if not ready */
        n = recv(c->sock, message + bytes, length - bytes, 0);
        if (n < 0) {
            perror("recv failed");
            exit(1);
        } else if (n == 0) {
            fprintf(stderr, "Connection closed on socket %d\n", c->sock);
            BRCloseConnection(c);
            return;
        }

        bytes += n;
    }
    if (bytes != length) {
        fprintf(stderr, "Too many bytes read (%d, not %d)\n", bytes, length);
        exit(1);
    }

    /* Generate CBByteArray of message for use in certain protocol commands */
    CBByteArray *ba = CBNewByteArrayWithDataCopy((uint8_t *) message, length);
#ifdef BRDEBUG
    print_header(header);
    printf("message len: %d\n", length);
    print_hex(ba);
#endif

    /* TODO verify checksum? */

    if (!strncmp(header + CB_MESSAGE_HEADER_TYPE, "version\0\0\0\0\0", 12)) {
        printf("Received version header\n\n");
        c->ver_received = 1; /* we received their version */
        BRSendVerack(c);
    } else if (!strncmp(header + CB_MESSAGE_HEADER_TYPE, "verack\0\0\0\0\0\0", 12)) {
        printf("Received verack header\n\n");
        c->ver_acked = 1; /* they've acknowledged our version */
        BRSendGetAddr(c);
    }
    
    if (BRVersionExchanged(c)) {
        if (!strncmp(header + CB_MESSAGE_HEADER_TYPE, "ping\0\0\0\0\0\0\0\0", 12)) {
            printf("Received ping header\n\n");
            BRSendPong(c, ba, length);
        } else if (!strncmp(header + CB_MESSAGE_HEADER_TYPE, "pong\0\0\0\0\0\0\0\0", 12)) {
            printf("Received pong header\n\n");
            /* TODO verify nonce */
        } else if (!strncmp(header + CB_MESSAGE_HEADER_TYPE, "inv\0\0\0\0\0\0\0\0\0", 12)) {
            printf("Received inv header\n\n");
            BRHandleInv(c, ba); /* possibly sends a getdata message in response */
        } else if (!strncmp(header + CB_MESSAGE_HEADER_TYPE, "addr\0\0\0\0\0\0\0\0", 12)) {
            printf("Received addr header\n\n");
            BRHandleAddr(c, ba);
        } else if (!strncmp(header + CB_MESSAGE_HEADER_TYPE, "getaddr\0\0\0\0\0", 12)) {
            printf("Received getaddr header\n\n");
            BRSendAddr(c);
        } else if (!strncmp(header + CB_MESSAGE_HEADER_TYPE, "tx\0\0\0\0\0\0\0\0\0\0", 12)) {
            printf("Received tx header\n\n");
            /* TODO handle transaction */
        } else if (!strncmp(header + CB_MESSAGE_HEADER_TYPE, "block\0\0\0\0\0\0\0", 12)) {
            printf("Received block header\n\n");
            BRHandleBlock(c, ba);
        }



        if (!c->addr_sent) {
            BRSendAddr(c);
        }
        if (!c->getblocks_sent) {
            /* TODO should wait for blocks instead of spamming getblocks
             * after every inv received; maybe change it to
             * blocks_received instead of getblocks_sent */
            BRSendGetBlocks(c);
        }
    }

    /* reference counter should be 0 now */
    CBReleaseObject(ba);
    free(message);
}
Ejemplo n.º 14
0
CBOnMessageReceivedAction CBNodeSendBlocksInvOrHeaders(CBNode * self, CBPeer * peer, CBGetBlocks * getBlocks, bool full){
	CBChainDescriptor * chainDesc = getBlocks->chainDescriptor;
	if (chainDesc->hashNum == 0)
		// Why do this?
		return CB_MESSAGE_ACTION_DISCONNECT;
	uint8_t branch;
	uint32_t blockIndex;
	// Go though the chain descriptor until a hash is found that we own
	bool found = false;
	// Lock block mutex for block chain access
	CBMutexLock(self->blockAndTxMutex);
	for (uint16_t x = 0; x < chainDesc->hashNum; x++) {
		CBErrBool exists = CBBlockChainStorageGetBlockLocation(CBGetNode(self)->validator, CBByteArrayGetData(chainDesc->hashes[x]), &branch, &blockIndex);
		if (exists == CB_ERROR) {
			CBMutexUnlock(self->blockAndTxMutex);
			return CBNodeReturnError(self, "Could not look for block with chain descriptor hash.");
		}
		if (exists == CB_TRUE) {
			// We have a block that we own.
			found = true;
			break;
		}
	}
	// Get the chain path for the main chain
	CBChainPath mainChainPath = CBValidatorGetMainChainPath(self->validator);
	CBChainPathPoint intersection;
	if (found){
		// Get the chain path for the block header we have found
		CBChainPath peerChainPath = CBValidatorGetChainPath(self->validator, branch, blockIndex);
		// Determine where the intersection is on the main chain
		intersection = CBValidatorGetChainIntersection(&mainChainPath, &peerChainPath);
	}else{
		// Bad chain?
		CBMutexUnlock(self->blockAndTxMutex);
		return CB_MESSAGE_ACTION_DISCONNECT;
	}
	CBMessage * message;
	// Now provide headers from this intersection up to 2000 blocks or block inventory items up to 500, the last one we have or the stopAtHash.
	for (uint16_t x = 0; x < (full ? 500 : 2000); x++) {
		// Check to see if we reached the last block in the main chain.
		if (intersection.chainPathIndex == 0
			&& intersection.blockIndex == mainChainPath.points[0].blockIndex) {
			if (x == 0){
				// The intersection is at the last block. The peer is up-to-date with us
				peer->upload = false;
				peer->upToDate = true;
				CBMutexUnlock(self->blockAndTxMutex);
				return CB_MESSAGE_ACTION_CONTINUE;
			}
			break;
		}
		// Move to the next block
		if (intersection.blockIndex == mainChainPath.points[intersection.chainPathIndex].blockIndex) {
			// Move to next branch
			intersection.chainPathIndex--;
			intersection.blockIndex = 0;
		}else
			// Move to the next block
			intersection.blockIndex++;
		// Get the hash
		uint8_t hash[32];
		if (! CBBlockChainStorageGetBlockHash(self->validator, mainChainPath.points[intersection.chainPathIndex].branch, intersection.blockIndex, hash)) {
			if (x != 0) CBReleaseObject(message);
			CBMutexUnlock(self->blockAndTxMutex);
			return CBNodeReturnError(self, "Could not obtain a hash for a block.");
		}
		// Check to see if we are at stopAtHash
		if (getBlocks->stopAtHash && memcmp(hash, CBByteArrayGetData(getBlocks->stopAtHash), 32) == 0){
			if (x == 0) {
				CBMutexUnlock(self->blockAndTxMutex);
				return CB_MESSAGE_ACTION_CONTINUE;
			}
			break;
		}
		if (x == 0){
			// Create inventory or block headers object to send to peer.
			if (full) {
				message = CBGetMessage(CBNewInventory());
				message->type = CB_MESSAGE_TYPE_INV;
			}else{
				message = CBGetMessage(CBNewBlockHeaders());
				message->type = CB_MESSAGE_TYPE_HEADERS;
			}
		}
		// Add block header or add inventory item
		if (full) {
			CBByteArray * hashObj = CBNewByteArrayWithDataCopy(hash, 32);
			char blkStr[CB_BLOCK_HASH_STR_SIZE];
			CBByteArrayToString(hashObj, 0, CB_BLOCK_HASH_STR_BYTES, blkStr, true);
			CBInventoryTakeInventoryItem(CBGetInventory(message), CBNewInventoryItem(CB_INVENTORY_ITEM_BLOCK, hashObj));
			CBReleaseObject(hashObj);
		}else
			CBBlockHeadersTakeBlockHeader(CBGetBlockHeaders(message), CBBlockChainStorageGetBlockHeader(self->validator, mainChainPath.points[intersection.chainPathIndex].branch, intersection.blockIndex));
	}
	CBMutexUnlock(self->blockAndTxMutex);
	// Send the message
	CBNodeSendMessageOnNetworkThread(CBGetNetworkCommunicator(self), peer, message, NULL);
	CBReleaseObject(message);
	// We are uploading to the peer
	peer->upload = true;
	return CB_MESSAGE_ACTION_CONTINUE;
}
Ejemplo n.º 15
0
uint32_t CBTransactionDeserialise(CBTransaction * self){
	CBByteArray * bytes = CBGetMessage(self)->bytes;
	if (NOT bytes) {
		CBLogError("Attempting to deserialise a CBTransaction with no bytes.");
		return 0;
	}
	if (bytes->length < 10) {
		CBLogError("Attempting to deserialise a CBTransaction with less than 10 bytes.");
		return 0;
	}
	self->version = CBByteArrayReadInt32(bytes, 0);
	CBVarInt inputOutputLen = CBVarIntDecode(bytes, 4);
	if (NOT inputOutputLen.val
		|| inputOutputLen.val * 41 > bytes->length - 10) {
		CBLogError("Attempting to deserialise a CBTransaction with a bad var int for the number of inputs.");
		return 0;
	}
	uint32_t cursor = 4 + inputOutputLen.size;
	self->inputNum = (uint32_t)inputOutputLen.val;
	self->inputs = malloc(sizeof(*self->inputs) * self->inputNum);
	if (NOT self->inputs) {
		CBLogError("Cannot allocate %i bytes of memory in CBTransactionDeserialise for inputs.\n", sizeof(*self->inputs) * self->inputNum);
		return 0;
	}
	for (uint32_t x = 0; x < self->inputNum; x++) {
		CBByteArray * data = CBByteArraySubReference(bytes, cursor, bytes->length-cursor);
		if (NOT data) {
			CBLogError("Cannot create a new CBByteArray in CBTransactionDeserialise for the input number %u.", x);
			return 0;
		}
		CBTransactionInput * input = CBNewTransactionInputFromData(data);
		if (NOT input) {
			CBLogError("Cannot create a new CBTransactionInput in CBTransactionDeserialise for the input number %u.", x);
			CBReleaseObject(data);
			return 0;
		}
		uint32_t len = CBTransactionInputDeserialise(input);
		if (NOT len){
			CBLogError("CBTransaction cannot be deserialised because of an error with the input number %u.", x);
			CBReleaseObject(data);
			return 0;
		}
		// The input was deserialised correctly. Now adjust the length and add it to the transaction.
		data->length = len;
		CBReleaseObject(data);
		self->inputs[x] = input;
		cursor += len; // Move along to next input
	}
	if (bytes->length < cursor + 5) { // Needs at least 5 more for the output CBVarInt and the lockTime
		CBLogError("Attempting to deserialise a CBTransaction with not enough bytes for the outputs and lockTime.");
		return 0;
	}
	inputOutputLen = CBVarIntDecode(bytes, cursor);
	if (NOT inputOutputLen.val
		|| inputOutputLen.val * 9 > bytes->length - 10) {
		CBLogError("Attempting to deserialise a CBTransaction with a bad var int for the number of outputs.");
		return 0;
	}
	cursor += inputOutputLen.size; // Move past output CBVarInt
	self->outputNum = (uint32_t)inputOutputLen.val;
	self->outputs = malloc(sizeof(*self->outputs) * self->outputNum);
	if (NOT self->outputs) {
		CBLogError("Cannot allocate %i bytes of memory in CBTransactionDeserialise for outputs.\n", sizeof(sizeof(*self->outputs) * self->outputNum));
		return 0;
	}
	for (uint32_t x = 0; x < self->outputNum; x++) {
		CBByteArray * data = CBByteArraySubReference(bytes, cursor, bytes->length-cursor);
		if (NOT data) {
			CBLogError("Cannot create a new CBByteArray in CBTransactionDeserialise for the output number %u.", x);
			return 0;
		}
		CBTransactionOutput * output = CBNewTransactionOutputFromData(data);
		if (NOT output) {
			CBLogError("Cannot create a new CBTransactionOutput in CBTransactionDeserialise for the output number %u.", x);
			CBReleaseObject(data);
			return 0;
		}
		uint32_t len = CBTransactionOutputDeserialise(output);
		if (NOT len){
			CBLogError("CBTransaction cannot be deserialised because of an error with the output number %u.", x);
			CBReleaseObject(data);
			return 0;
		}
		// The output was deserialised correctly. Now adjust the length and add it to the transaction.
		data->length = len;
		CBReleaseObject(data);
		self->outputs[x] = output;
		cursor += len; // Move along to next output
	}
	if (bytes->length < cursor + 4) { // Ensure 4 bytes are available for lockTime
		CBLogError("Attempting to deserialise a CBTransaction with not enough bytes for the lockTime.");
		return 0;
	}
	self->lockTime = CBByteArrayReadInt32(bytes, cursor);
	return cursor + 4;
}
Ejemplo n.º 16
0
int main(){
	printf("OpenSSL version: %s\n", OPENSSL_VERSION_TEXT);
	printf("Enter the number of keys: ");
	fflush(stdout);
	char stringMatch[31];
	getLine(stringMatch);
	unsigned long int i = strtol(stringMatch, NULL, 0);
	printf("Enter a string of text for the key (30 max): ");
	fflush(stdout);
	getLine(stringMatch);
	printf("Waiting for entropy... Move the cursor around...\n");
	fflush(stdout);
	char entropy[32];
	FILE * f = fopen("/dev/random", "r");
	if (fread(entropy, 32, 1, f) != 1){
		printf("FAILURING GETTING ENTROPY!");
		return 1;
	}
	RAND_add(entropy, 32, 32);
	fclose(f);
	printf("Making %lu addresses for \"%s\"\n\n", i, stringMatch);
	EC_KEY * key = EC_KEY_new_by_curve_name(NID_secp256k1);
	uint8_t * pubKey = NULL;
	int pubSize = 0;
	uint8_t * privKey = NULL;
	int privSize = 0;
	uint8_t * shaHash = malloc(32);
	uint8_t * ripemdHash = malloc(20);
	for (unsigned int x = 0; x < i;) {
		if(! EC_KEY_generate_key(key)){
			printf("GENERATE KEY FAIL\n"); 
			return 1;
		}
		int pubSizeNew = i2o_ECPublicKey(key, NULL);
		if(! pubSizeNew){
			printf("PUB KEY TO DATA ZERO\n"); 
			return 1;
		}
		if (pubSizeNew != pubSize) {
			pubSize = pubSizeNew;
			pubKey = realloc(pubKey, pubSize);
		}
		uint8_t * pubKey2 = pubKey;
		if(i2o_ECPublicKey(key, &pubKey2) != pubSize){
			printf("PUB KEY TO DATA FAIL\n");
			return 1;
		}
		SHA256(pubKey, pubSize, shaHash);
		RIPEMD160(shaHash, 32, ripemdHash);
		CBAddress * address = CBNewAddressFromRIPEMD160Hash(ripemdHash, CB_PRODUCTION_NETWORK_BYTE, false, err);
		CBByteArray * string = CBChecksumBytesGetString(CBGetChecksumBytes(address));
		CBReleaseObject(address);
		bool match = true;
		uint8_t offset = 1;
		size_t matchSize = strlen(stringMatch);
		for (uint8_t y = 0; y < matchSize;) {
			char other = islower(stringMatch[y]) ? toupper(stringMatch[y]) : (isupper(stringMatch[y])? tolower(stringMatch[y]) : '\0');
			if (CBByteArrayGetByte(string, y+offset) != stringMatch[y] && CBByteArrayGetByte(string, y+offset) != other) {
				offset++;
				y = 0;
				if (string->length < matchSize + offset) {
					match = false;
					break;
				}
			}else y++;
		}
		if (match) {
			// Get private key
			const BIGNUM * privKeyNum = EC_KEY_get0_private_key(key);
			if (! privKeyNum) {
				printf("PRIV KEY TO BN FAIL\n");
			}
			int privSizeNew = BN_num_bytes(privKeyNum);
			if (privSizeNew != privSize) {
				privSize = privSizeNew;
				privKey = realloc(privKey, privSize);
			}
			int res = BN_bn2bin(privKeyNum, privKey);
			if (res != privSize) {
				printf("PRIV KEY TO DATA FAIL\n");
			}
			// Print data to stdout
			printf("Private key (hex): ");
			for (int x = 0; x < privSize; x++) {
				printf(" %.2X", privKey[x]);
			}
			printf("\nPublic key (hex): ");
			for (int x = 0; x < pubSize; x++) {
				printf(" %.2X", pubKey[x]);
			}
			printf("\nAddress (base-58): %s\n\n", CBByteArrayGetData(string));
			x++; // Move to next
		}
		CBReleaseObject(string);
	}
	free(shaHash);
	free(ripemdHash);
	EC_KEY_free(key);
	return 0;
}
Ejemplo n.º 17
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 vi = CBVarIntFromUInt64(prevOutSubScript->length);
	uint32_t sizeOfData = 12 + prevOutSubScript->length + vi.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, 1 for varInt, 4 for sequence
	}else{
		sizeOfData += CBVarIntSizeOf(self->inputNum) + self->inputNum * 40 + (self->inputNum - 1); // All inputs
	}
	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
		CBByteArrayCopyByteArray(data, 41, prevOutSubScript);
		cursor = 41 + 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, vi);
				cursor += vi.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);
	CBReleaseObject(data);
	return CB_TX_HASH_OK;
}
Ejemplo n.º 18
0
void checkKey(CBHDKey * key, uint8_t x, uint8_t y){
	// Check version bytes
	if (key->versionBytes != CB_HD_KEY_VERSION_PROD_PRIVATE) {
		printf("VERSION BYTES FAIL AT %u - %u\n", x, y);
		exit(EXIT_FAILURE);
	}
	// Check address
	CBAddress * address = CBNewAddressFromRIPEMD160Hash(CBHDKeyGetHash(key), CB_NETWORK_PRODUCTION, false);
	CBByteArray * str = CBChecksumBytesGetString(CBGetChecksumBytes(address));
	CBReleaseObject(address);
	if (memcmp(CBByteArrayGetData(str), testVectors[x][y].addr, 34) != 0) {
		printf("ADDR FAIL AT %u - %u\n", x, y);
		exit(EXIT_FAILURE);
	}
	CBReleaseObject(str);
	// Check WIF
	CBWIF * wif = CBHDKeyGetWIF(key);
	str = CBChecksumBytesGetString(CBGetChecksumBytes(wif));
	CBReleaseObject(wif);
	if (memcmp(CBByteArrayGetData(str), testVectors[x][y].WIF, 52) != 0) {
		printf("WIF FAIL AT %u - %u\n", x, y);
		exit(EXIT_FAILURE);
	}
	CBReleaseObject(str);
	// Check chain code
	if (memcmp(key->chainCode, testVectors[x][y].chainCode, 32) != 0) {
		printf("CHAIN CODE FAIL AT %u - %u\n", x, y);
		exit(EXIT_FAILURE);
	}
	// Check child ID
	if (memcmp(&key->childID, &testVectors[x][y].childID, sizeof(key->childID)) != 0) {
		printf("CHILD ID FAIL AT %u - %u\n", x, y);
		exit(EXIT_FAILURE);
	}
	// Check depth
	if (key->depth != y) {
		printf("DEPTH FAIL AT %u - %u\n", x, y);
		exit(EXIT_FAILURE);
	}
	// Check serialisation of private key
	uint8_t * keyData = malloc(82);
	CBHDKeySerialise(key, keyData);
	CBChecksumBytes * checksumBytes = CBNewChecksumBytesFromBytes(keyData, 82, false);
	str = CBChecksumBytesGetString(checksumBytes);
	CBReleaseObject(checksumBytes);
	if (memcmp(CBByteArrayGetData(str), testVectors[x][y].privString, 111) != 0) {
		printf("PRIVATE KEY STRING FAIL AT %u - %u\n", x, y);
		exit(EXIT_FAILURE);
	}
	CBReleaseObject(str);
	// Check serialisation of public key
	key->versionBytes = CB_HD_KEY_VERSION_PROD_PUBLIC;
	keyData = malloc(82);
	CBHDKeySerialise(key, keyData);
	checksumBytes = CBNewChecksumBytesFromBytes(keyData, 82, false);
	str = CBChecksumBytesGetString(checksumBytes);
	CBReleaseObject(checksumBytes);
	if (memcmp(CBByteArrayGetData(str), testVectors[x][y].pubString, 111) != 0) {
		printf("PUBLIC KEY STRING FAIL AT %u - %u\n", x, y);
		exit(EXIT_FAILURE);
	}
	CBReleaseObject(str);
	// Make private again
	key->versionBytes = CB_HD_KEY_VERSION_PROD_PRIVATE;
}
Ejemplo n.º 19
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;
	}
}
Ejemplo n.º 20
0
int main(){
	CBByteArray * walletKeyString = CBNewByteArrayFromString("xpub6DRhpXssnj7X6CwJgseK9oyFxSC8jk6nJz2SWkf5pjsQs12xv89Dfr627TtaZKkFbG6Aq23fmaNaf5KRo9iGfEXTTXvtd6gsXJTB8Sdah3B", false);
    CBChecksumBytes * walletKeyData = CBNewChecksumBytesFromString(walletKeyString, false);
    CBHDKey * cbkey = CBNewHDKeyFromData(CBByteArrayGetData(CBGetByteArray(walletKeyData)));
	CBAddress * address = CBNewAddressFromRIPEMD160Hash(CBHDKeyGetHash(cbkey), CB_NETWORK_PRODUCTION, false);
	CBByteArray * str = CBChecksumBytesGetString(CBGetChecksumBytes(address));
	printf("%s\n", CBByteArrayGetData(str));
	CBReleaseObject(address);
	// Test type
	if (CBHDKeyGetType(CB_HD_KEY_VERSION_PROD_PRIVATE) != CB_HD_KEY_TYPE_PRIVATE) {
		printf("CB_HD_KEY_VERSION_PROD_PRIVATE TYPE FAIL\n");
		return EXIT_FAILURE;
	}
	if (CBHDKeyGetType(CB_HD_KEY_VERSION_PROD_PUBLIC) != CB_HD_KEY_TYPE_PUBLIC) {
		printf("CB_HD_KEY_VERSION_PROD_PUBLIC TYPE FAIL\n");
		return EXIT_FAILURE;
	}
	if (CBHDKeyGetType(CB_HD_KEY_VERSION_TEST_PRIVATE) != CB_HD_KEY_TYPE_PRIVATE) {
		printf("CB_HD_KEY_VERSION_TEST_PRIVATE TYPE FAIL\n");
		return EXIT_FAILURE;
	}
	if (CBHDKeyGetType(CB_HD_KEY_VERSION_TEST_PUBLIC) != CB_HD_KEY_TYPE_PUBLIC) {
		printf("CB_HD_KEY_VERSION_TEST_PUBLIC TYPE FAIL\n");
		return EXIT_FAILURE;
	}
	// Test HMAC-SHA512
	uint8_t hash[64];
	CBHDKeyHmacSha512((uint8_t [37]){0x2f, 0xf7, 0xd6, 0x9f, 0x7a, 0x59, 0x0b, 0xb0, 0x5e, 0x68, 0xd1, 0xdc, 0x0f, 0xcf, 0x8d, 0xc2, 0x17, 0x59, 0xc9, 0x39, 0xbb, 0x6b, 0x9b, 0x02, 0x0f, 0x65, 0x5d, 0x53, 0x85, 0x3c, 0xb5, 0xc2, 0x14, 0x61, 0x4b, 0x24, 0x42}, (uint8_t [32]){0xa2, 0x55, 0x21, 0xe3, 0xc5, 0x5b, 0x65, 0xd1, 0xcf, 0x25, 0x4b, 0x6c, 0x85, 0x23, 0xdc, 0xbf, 0x89, 0x46, 0x8d, 0x1f, 0x09, 0x1f, 0x15, 0x87, 0x6b, 0xbb, 0xc7, 0xfd, 0xd5, 0x44, 0x28, 0x43}, hash);
	if (memcmp(hash, (uint8_t [64]){0xfa, 0xa7, 0x9d, 0x85, 0xe0, 0xe4, 0x3d, 0xae, 0x8c, 0x3f, 0x99, 0xf0, 0x70, 0xdf, 0x97, 0x56, 0x2b, 0x3f, 0xbb, 0x17, 0x35, 0x20, 0xe0, 0x87, 0x32, 0xa6, 0x64, 0xca, 0xd4, 0x55, 0x0b, 0xbe, 0xc1, 0x11, 0xe5, 0xf8, 0x80, 0xdb, 0xb7, 0x3d, 0x67, 0x74, 0xbb, 0xc2, 0x9f, 0x67, 0xd9, 0x67, 0xaa, 0x10, 0xac, 0x60, 0x18, 0x90, 0x7f, 0x35, 0x53, 0xe3, 0x21, 0x38, 0xf6, 0x5b, 0xbe, 0x69}, 64) != 0) {
		printf("HMAC FAIL\n");
		return EXIT_FAILURE;
	}
	for (uint8_t x = 0; x < NUM_TEST_VECTORS; x++) {
		// Deserialise private key
		CBByteArray * masterString = CBNewByteArrayFromString(testVectors[x][0].privString, true);
		CBChecksumBytes * masterData = CBNewChecksumBytesFromString(masterString, false);
		CBReleaseObject(masterString);
		CBHDKey * key = CBNewHDKeyFromData(CBByteArrayGetData(CBGetByteArray(masterData)));
		CBReleaseObject(masterData);
		checkKey(key, x, 0);
		for (uint8_t y = 0; y < NUM_CHILDREN; y++) {
			if (testVectors[x][y+1].childID.priv == false) {
				// Derive public child and check public key is correct by address
				CBHDKey * newKey = CBNewHDKey(false);
				key->versionBytes = CB_HD_KEY_VERSION_PROD_PUBLIC;
				CBHDKeyDeriveChild(key, testVectors[x][y+1].childID, newKey);
				key->versionBytes = CB_HD_KEY_VERSION_PROD_PRIVATE;
				CBAddress * address = CBNewAddressFromRIPEMD160Hash(CBHDKeyGetHash(newKey), CB_NETWORK_PRODUCTION, false);
				CBByteArray * str = CBChecksumBytesGetString(CBGetChecksumBytes(address));
				CBReleaseObject(address);
				if (memcmp(CBByteArrayGetData(str), testVectors[x][y + 1].addr, 34) != 0) {
					printf("ADDR FROM PUB FAIL AT %u - %u\n", x, y + 1);
					exit(EXIT_FAILURE);
				}
				CBReleaseObject(str);
				// Check serialisation of public key
				uint8_t * keyData = malloc(82);
				CBHDKeySerialise(newKey, keyData);
				CBChecksumBytes * checksumBytes = CBNewChecksumBytesFromBytes(keyData, 82, false);
				str = CBChecksumBytesGetString(checksumBytes);
				CBReleaseObject(checksumBytes);
				if (memcmp(CBByteArrayGetData(str), testVectors[x][y+1].pubString, 111) != 0) {
					printf("PUBLIC KEY STRING FROM PUB FAIL AT %u - %u\n", x, y);
					exit(EXIT_FAILURE);
				}
				CBReleaseObject(str);
				free(newKey);
			}
			// Derive private child
			CBHDKey * newKey = CBNewHDKey(true);
			CBHDKeyDeriveChild(key, testVectors[x][y+1].childID, newKey);
			free(key);
			key = newKey;
			checkKey(key, x, y+1);
		}
		free(key);
	}
	return EXIT_SUCCESS;
}
Ejemplo n.º 21
0
void CBFreeInventoryItem(void * vself){
	CBInventoryItem * self = vself;
	CBReleaseObject(self->hash);
	CBFreeMessage(self);
}
Ejemplo n.º 22
0
void CBNodeDisconnectPeerRun(void * vpeer){
	CBPeer * peer = vpeer;
	CBNetworkCommunicator * comm = peer->nodeObj;
	CBNetworkCommunicatorDisconnect(comm, peer, CB_24_HOURS, false);
	CBReleaseObject(peer);
}