示例#1
0
int main(){
	unsigned int s = (unsigned int)time(NULL);
	printf("Session = %ui\n", s);
	srand(s);
	// Test string
	char * string = "Hello World!";
	CBByteArray * ba = CBNewByteArrayWithDataCopy((uint8_t *)string, (uint32_t)strlen(string) + 1);
	if (strcmp(string, (char *)CBByteArrayGetData(ba))) {
		printf("STRING COPY FAIL\n");
		return 1;
	}
	return 0;
}
示例#2
0
void BRSendPing(BRConnection *c) {
    printf("Sending ping\n");
    
    CBMessage *m = CBNewMessageByObject();
    uint64_t nonce = rand();
    CBByteArray *ba = CBNewByteArrayWithDataCopy((uint8_t *) &nonce, 8);
    CBInitMessageByData(m, ba);

    BRSendMessage(c, m, "ping");

    CBReleaseObject(ba);
    CBFreeMessage(m);
}
int
main (void)
{
    // use the default event loop unless you have special needs
    struct ev_loop *loop = ev_default_loop (0);
    printf("Type help for a list of commands\n");

    CBByteArray *ip = CBNewByteArrayWithDataCopy((uint8_t [16]){0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xFF, 0xFF, 128, 8, 126, 25}, 16);
    CBNetworkAddress *peeraddr = CBNewNetworkAddress(0, ip, DEFAULT_PORT, CB_SERVICE_FULL_BLOCKS, false);
    peer = CBNewPeerByTakingNetworkAddress(peeraddr);

    // Create client socket
    if( (sd = socket(PF_INET, SOCK_STREAM, 0)) < 0) {
        perror("socket error");
        return -1;
    }
    memset(&addr, sizeof(addr), 0);
    addr.sin_family = AF_INET;
    addr.sin_port = htons(DEFAULT_PORT);
    addr.sin_addr.s_addr = (((((25 << 8) | 126) << 8) | 8) << 8) | 128;

    // Connect to server socket
    if(connect(sd, (struct sockaddr *)&addr, sizeof addr) < 0) {
        perror("Connect error");
        return -1;
    }

    printf("Connected to %s:%d\n", DEFAULT_IP, DEFAULT_PORT);
    
    // initialise an io watcher, then start it
    // this one will watch for stdin to become readable
    ev_io_init (&stdin_watcher, stdin_cb, /*STDIN_FILENO*/ 0, EV_READ);
    ev_io_start (loop, &stdin_watcher);

    // io watcher for the socket
    ev_io_init (&sock_watcher, sockread_cb, sd, EV_READ);
    ev_io_start (loop, &sock_watcher);

    // initialise a timer watcher, then start it
    ev_timer_init (&timeout_watcher, timeout_cb, 2.0, 0.);
    ev_timer_start (loop, &timeout_watcher);

    // now wait for events to arrive
    ev_loop (loop, 0);

    // unloop was called, so exit
    return 0;
}
示例#4
0
bool CBInitBlockGenesis(CBBlock * self){
	CBByteArray * data = CBNewByteArrayWithDataCopy((uint8_t [285]){0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 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, 0x29, 0xAB, 0x5F, 0x49, 0xFF, 0xFF, 0x00, 0x1D, 0x1D, 0xAC, 0x2B, 0x7C, 0x01, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x4D, 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, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0x00, 0xF2, 0x05, 0x2A, 0x01, 0x00, 0x00, 0x00, 0x43, 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, 0x00, 0x00, 0x00, 0x00}, 285);
	if (NOT data)
		return false;
	uint8_t genesisHash[32] = {0x6F, 0xE2, 0x8C, 0x0A, 0xB6, 0xF1, 0xB3, 0x72, 0xC1, 0xA6, 0xA2, 0x46, 0xAE, 0x63, 0xF7, 0x4F, 0x93, 0x1E, 0x83, 0x65, 0xE1, 0x5A, 0x08, 0x9C, 0x68, 0xD6, 0x19, 0x00, 0x00, 0x00, 0x00, 0x00};
	memcpy(self->hash, genesisHash, 32);
	self->hashSet = true;
	if (NOT CBInitMessageByData(CBGetMessage(self), data)){
		CBReleaseObject(data);
		CBReleaseObject(self->hash);
		return false;
	}
	CBReleaseObject(data);
	CBBlockDeserialise(self, true);
	return true;
}
示例#5
0
bool CBAddressStorageLoadAddresses(uint64_t iself, void * addrMan){
	CBDatabase * database = (CBDatabase *)iself;
	CBAddressManager * addrManObj = addrMan;
	CBPosition it;
	// The first element shoudl be the number of addresses so get second element to begin with.
	if (CBAssociativeArrayGetElement(&database->index, &it, 1)) for(;;) {
		uint8_t * key = it.node->elements[it.index];
		CBIndexValue * val = (CBIndexValue *)(key + *key + 1);
		if (val->length) {
			// Is not deleted.
			// Read data
			uint64_t file = CBDatabaseGetFile(database, val->fileID);
			if (NOT file) {
				CBLogError("Could not open a file for loading a network address.");
				return false;
			}
			if (NOT CBFileSeek(file, val->pos)){
				CBLogError("Could not read seek a file to a network address.");
				return false;
			}
			if (NOT CBFileRead(file, CB_DATA_ARRAY, 20)) {
				CBLogError("Could not read a network address from a file.");
				return false;
			}
			// Create network address object and add to the address manager.
			CBByteArray * ip = CBNewByteArrayWithDataCopy(key + 1, 16);
			CBNetworkAddress * addr = CBNewNetworkAddress(CBArrayToInt64(CB_DATA_ARRAY, 0),
														  ip,
														  CBArrayToInt16(key, 17),
														  (CBVersionServices) CBArrayToInt64(CB_DATA_ARRAY, 8),
														  true);
			addr->penalty = CBArrayToInt32(CB_DATA_ARRAY, 16);
			if (NOT CBAddressManagerTakeAddress(addrManObj, addr)) {
				CBLogError("Could not create and add a network address to the address manager.");
				return false;
			}
			CBReleaseObject(ip);
		}
		if (CBAssociativeArrayIterate(&database->index, &it))
			break;
	}
	return true;
}
static void
send_version() 
{
    CBByteArray *ip = CBNewByteArrayWithDataCopy((uint8_t [16]){0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xFF, 0xFF, 127, 0, 0, 1}, 16);
    CBByteArray *ua = CBNewByteArrayFromString("cmsc417versiona", '\00');
    CBNetworkAddress * sourceAddr = CBNewNetworkAddress(0, ip, 0, CB_SERVICE_FULL_BLOCKS, false);
    int32_t vers = 70001;
    int nonce = rand();
    CBVersion * version = CBNewVersion(vers, CB_SERVICE_FULL_BLOCKS, time(NULL), &peer->base, sourceAddr, nonce, ua, 0);
    CBMessage *message = CBGetMessage(version);
    char header[24];
    memcpy(header + CB_MESSAGE_HEADER_TYPE, "version\0\0\0\0\0", 12);

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

    // Send the header
    send(sd, header, 24, 0);
    
    // Send the message
    printf("message len: %d\n", message->bytes->length);
    printf("checksum: %x\n", *((uint32_t *) message->checksum));
    send(sd, message->bytes->sharedData->data+message->bytes->offset, message->bytes->length, 0);
    print_hex(message->bytes);
}
示例#7
0
void BRSendGetBlocks(BRConnection *c) {
    BRConnector *connector = (BRConnector *) c->connector;
    CBChainDescriptor *chain = BRKnownBlocks(connector->block_chain);

    /* 0 to get as many blocks as possible (500) */
    uint8_t zero[32] = {0};
    CBByteArray *stop = CBNewByteArrayWithDataCopy(zero, 32);

    CBGetBlocks *get_blocks = CBNewGetBlocks(VERSION_NUM, chain, stop);

    uint32_t length = CBGetBlocksCalculateLength(get_blocks);
    get_blocks->base.bytes = CBNewByteArrayOfSize(length);
    CBGetBlocksSerialise(get_blocks, false);
    BRSendMessage(c, &get_blocks->base, "getblocks");

    CBReleaseObject(stop);
    CBReleaseObject(chain);
    CBFreeGetBlocks(get_blocks);

    /* update with sent getblocks */
    c->getblocks_sent = 1;
}
示例#8
0
int main(){
	unsigned int s = (unsigned int)time(NULL);
	s = 1337544566;
	printf("Session = %ui\n",s);
	srand(s);
	// Test deserialisation of real alert
	uint8_t data[188] = {
		0x73, // Length of payload
		0x01,0x00,0x00,0x00, // Version 1
		0x37,0x66,0x40,0x4F,0x00,0x00,0x00,0x00, // Relay until 1329620535
		0xB3,0x05,0x43,0x4F,0x00,0x00,0x00,0x00, // Expires at 1329792435
		0xF2,0x03,0x00,0x00, // ID 1010
		0xF1,0x03,0x00,0x00, // Cancel < 1009
		0x00, // No more IDs
		0x10,0x27,0x00,0x00, // Min version 10000
		0x48,0xee,0x00,0x00, // Max version 61000
		0x00, // No user agents
		0x64,0x00,0x00,0x00, // Priority 100
		0x00, // Empty hidden comment
		0x46, // Displayed comment is 70 characters long
		// "See bitcoin.org/feb20 if you have trouble connecting after 20 February"
		0x53,0x65,0x65,0x20,0x62,0x69,0x74,0x63,0x6F,0x69,0x6E,0x2E,0x6F,0x72,0x67,0x2F,0x66,0x65,0x62,0x32,0x30,0x20,0x69,0x66,0x20,0x79,0x6F,0x75,0x20,0x68,0x61,0x76,0x65,0x20,0x74,0x72,0x6F,0x75,0x62,0x6C,0x65,0x20,0x63,0x6F,0x6E,0x6E,0x65,0x63,0x74,0x69,0x6E,0x67,0x20,0x61,0x66,0x74,0x65,0x72,0x20,0x32,0x30,0x20,0x46,0x65,0x62,0x72,0x75,0x61,0x72,0x79,
		0x00, // No reserved
		// Signature
		0x47, // Signature is 71 bytes long
		0x30,0x45,0x02,0x21,0x00,0x83,0x89,0xdf,0x45,0xF0,0x70,0x3F,0x39,0xEC,0x8C,0x1C,0xC4,0x2C,0x13,0x81,0x0F,0xFC,0xAE,0x14,0x99,0x5B,0xB6,0x48,0x34,0x02,0x19,0xE3,0x53,0xB6,0x3B,0x53,0xEB,0x02,0x20,0x09,0xEC,0x65,0xE1,0xC1,0xAA,0xEE,0xC1,0xFD,0x33,0x4C,0x6B,0x68,0x4B,0xDE,0x2B,0x3F,0x57,0x30,0x60,0xD5,0xb7,0x0C,0x3A,0x46,0x72,0x33,0x26,0xE4,0xE8,0xA4,0xF1
	};
	CBByteArray * bytes = CBNewByteArrayWithDataCopy(data, 188, logError);
	CBAlert * alert = CBNewAlertFromData(bytes, logError);
	if(CBAlertDeserialise(alert) != 188){
		printf("DESERIALISATION LEN FAIL\n");
		return 1;
	}
	if (alert->version != 1) {
		printf("DESERIALISATION VERSION FAIL\n");
		return 1;
	}
	if (alert->relayUntil != 1329620535) {
		printf("DESERIALISATION RELAY UNTIL FAIL\n");
		return 1;
	}
	if (alert->expiration != 1329792435) {
		printf("DESERIALISATION EXPIRATION FAIL\n");
		return 1;
	}
	if (alert->ID != 1010) {
		printf("DESERIALISATION ID FAIL\n");
		return 1;
	}
	if (alert->cancel != 1009) {
		printf("DESERIALISATION CANCEL FAIL\n");
		return 1;
	}
	if (alert->setCancelNum != 0) {
		printf("DESERIALISATION SET CANCEL NUM FAIL\n");
		return 1;
	}
	if (alert->setCancel != NULL) {
		printf("DESERIALISATION SET CANCEL FAIL\n");
		return 1;
	}
	if (alert->minVer != 10000) {
		printf("DESERIALISATION MIN VERSION FAIL\n");
		return 1;
	}
	if (alert->maxVer != 61000) {
		printf("DESERIALISATION MAX VERSION FAIL\n");
		return 1;
	}
	if (alert->userAgentNum != 0) {
		printf("DESERIALISATION USER AGENT NUM FAIL\n");
		return 1;
	}
	if (alert->userAgents != NULL) {
		printf("DESERIALISATION USER AGENTS FAIL\n");
		return 1;
	}
	if (alert->priority != 100) {
		printf("DESERIALISATION PRIORITY FAIL\n");
		return 1;
	}
	if (alert->hiddenComment != NULL) {
		printf("DESERIALISATION HIDDEN COMMENT FAIL\n");
		return 1;
	}
	if (memcmp(CBByteArrayGetData(alert->displayedComment),"See bitcoin.org/feb20 if you have trouble connecting after 20 February",70)) {
		printf("DESERIALISATION DISPLAYED COMMENT FAIL\n0x");
		char * d = (char *)CBByteArrayGetData(alert->displayedComment);
		for (int x = 0; x < 70; x++) {
			printf("%c",d[x]);
		}
		printf("\n!=\nSee bitcoin.org/feb20 if you have trouble connecting after 20 February\n");
		return 1;
	}
	if (alert->reserved != NULL) {
		printf("DESERIALISATION RESERVED FAIL\n");
		return 1;
	}
	// Check signature
	CBByteArray * payload = CBAlertGetPayload(alert);
	uint8_t hash1[32];
	CBSha256(CBByteArrayGetData(payload),payload->length,hash1);
	uint8_t hash2[32];
	CBSha256(hash1, 32,hash2);
	if (NOT CBEcdsaVerify(CBByteArrayGetData(alert->signature),alert->signature->length,hash2,(uint8_t [65]){0x04,0xFC,0x97,0x02,0x84,0x78,0x40,0xAA,0xF1,0x95,0xDE,0x84,0x42,0xEB,0xEC,0xED,0xF5,0xB0,0x95,0xCD,0xBB,0x9B,0xC7,0x16,0xBD,0xA9,0x11,0x09,0x71,0xB2,0x8A,0x49,0xE0,0xEA,0xD8,0x56,0x4F,0xF0,0xDB,0x22,0x20,0x9E,0x03,0x74,0x78,0x2C,0x09,0x3B,0xB8,0x99,0x69,0x2D,0x52,0x4E,0x9D,0x6A,0x69,0x56,0xE7,0xC5,0xEC,0xBC,0xD6,0x82,0x84},65)) {
		printf("DESERIALISATION SIG FAIL\n");
		return 1;
	}
	CBReleaseObject(payload);
	// Test serialisation
	memset(CBByteArrayGetData(bytes), 0, 188);
	CBReleaseObject(alert->displayedComment);
	alert->displayedComment = CBNewByteArrayWithDataCopy((uint8_t *)"See bitcoin.org/feb20 if you have trouble connecting after 20 February", 70, logError);
	CBReleaseObject(alert->signature);
	alert->signature = CBNewByteArrayWithDataCopy((uint8_t []){0x30,0x45,0x02,0x21,0x00,0x83,0x89,0xdf,0x45,0xF0,0x70,0x3F,0x39,0xEC,0x8C,0x1C,0xC4,0x2C,0x13,0x81,0x0F,0xFC,0xAE,0x14,0x99,0x5B,0xB6,0x48,0x34,0x02,0x19,0xE3,0x53,0xB6,0x3B,0x53,0xEB,0x02,0x20,0x09,0xEC,0x65,0xE1,0xC1,0xAA,0xEE,0xC1,0xFD,0x33,0x4C,0x6B,0x68,0x4B,0xDE,0x2B,0x3F,0x57,0x30,0x60,0xD5,0xb7,0x0C,0x3A,0x46,0x72,0x33,0x26,0xE4,0xE8,0xA4,0xF1}, 71, logError);
	CBAlertSerialisePayload(alert);
	if(CBAlertSerialiseSignature(alert, 116) != 188){
		printf("SERIALISATION LEN FAIL\n");
		return 1;
	}
	if (memcmp(data, CBByteArrayGetData(bytes), 188)) {
		printf("SERIALISATION FAIL\n0x");
		uint8_t * d = CBByteArrayGetData(bytes);
		for (int x = 0; x < 188; x++) {
			printf("%.2X",d[x]);
		}
		printf("\n!=\n0x");
		for (int x = 0; x < 188; x++) {
			printf("%.2X",data[x]);
		}
		return 1;
	}
	CBReleaseObject(alert);
	CBReleaseObject(bytes);
	return 0;
}
示例#9
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;
}
示例#10
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;
}
示例#11
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);
}
示例#12
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;
}