Exemplo n.º 1
0
int database_find_blockchain_transaction(struct database* db, unsigned char* hash, size_t max_height, struct transaction** tx, size_t* height)
{
    mongoc_collection_t* collection = mongoc_client_get_collection(db->client, database_name(db), "transactions");

    // Build a query doc
    bson_t* query = bson_new();

    // Set the hash
    BSON_APPEND_BINARY(query, "hash", BSON_SUBTYPE_BINARY, (uint8_t*)hash, 32);

    // Force the height to be valid (on the main chain)
    bson_t* height_doc = bson_new();
    BSON_APPEND_DOCUMENT_BEGIN(query, "height", height_doc);
    BSON_APPEND_INT32(height_doc, "$lte", (int)max_height);
    BSON_APPEND_INT32(height_doc, "$gte", 0);
    bson_append_document_end(query, height_doc);

    // Perform find
    mongoc_cursor_t* cursor = mongoc_collection_find(collection, MONGOC_QUERY_NONE, 0, 0, 0, query, NULL, NULL);

    bson_error_t error;
    if(cursor == NULL || mongoc_cursor_error(cursor, &error)) {
        printf("MongoDB error: %s\n", (cursor == NULL) ? "NULL cursor" : error.message);
        return -1;
    }

    bson_t const* doc;
    int found = 0;
    while(mongoc_cursor_next(cursor, &doc) != 0) {
        if(height != NULL) {
            bson_iter_t iter;
            if(!bson_iter_init_find(&iter, doc, "height") || !BSON_ITER_HOLDS_INT32(&iter)) {
                printf("MongoDB error: tx doesn't have height!\n");
                return -1;
            }
            *height = (size_t)bson_iter_int32(&iter);
        }

        if(tx != NULL) {
            *tx = transaction_from_bson(doc);
        }

        found = 1;
        break;
    }

    mongoc_cursor_destroy(cursor);
    bson_destroy(height_doc);
    bson_destroy(query);
    mongoc_collection_destroy(collection);
    return found;
}
Exemplo n.º 2
0
// Find the spend of a specified output_reference within a given blockheight range (main chain only)
// if found, load tx and the input that spends it
int database_find_blockchain_spend(struct database* db, struct transaction_output_reference* output_reference, size_t start_height, size_t max_height, struct transaction** tx)
{
    mongoc_collection_t* collection = mongoc_client_get_collection(db->client, database_name(db), "transactions");

    // Build a query doc
    bson_t* query = bson_new();

    // Build a query that tries to find where this output_reference is spent
    unsigned char hash[32];
    transaction_output_reference_hash(output_reference, hash);

    bson_t* output_reference_doc = bson_new();
    BSON_APPEND_DOCUMENT_BEGIN(query, "inputs.output_reference", output_reference_doc);
    BSON_APPEND_BINARY(output_reference_doc, "hash", BSON_SUBTYPE_BINARY, (uint8_t*)hash, 32);
    BSON_APPEND_INT32(output_reference_doc, "index", transaction_output_reference_index(output_reference));
    bson_append_document_end(query, output_reference_doc);

    // Force the height to be valid
    bson_t* height_doc = bson_new();
    BSON_APPEND_DOCUMENT_BEGIN(query, "height", height_doc);
    BSON_APPEND_INT32(height_doc, "$lte", (int)max_height);
    BSON_APPEND_INT32(height_doc, "$gte", start_height);
    bson_append_document_end(query, height_doc);

    // Perform find
    mongoc_cursor_t* cursor = mongoc_collection_find(collection, MONGOC_QUERY_NONE, 0, 0, 0, query, NULL, NULL);

    bson_error_t error;
    if(cursor == NULL || mongoc_cursor_error(cursor, &error)) {
        printf("MongoDB error: %s\n", (cursor == NULL) ? "NULL cursor" : error.message);
        return -1;
    }

    bson_t const* doc;
    int found = 0;
    while(mongoc_cursor_next(cursor, &doc) != 0) {
        if(tx != NULL) {
            *tx = transaction_from_bson(doc);
        }

        found = 1;
        break;
    }

    mongoc_cursor_destroy(cursor);
    bson_destroy(height_doc);
    bson_destroy(output_reference_doc);
    bson_destroy(query);
    mongoc_collection_destroy(collection);
    return found;
}
Exemplo n.º 3
0
 // ---------------------------------------------------------------------------------
 success Sqlite::open_database_connection() const
 {
   if ( prepare_storage_directory().has_failed() )
   {
     return error();
   }
   QSqlDatabase db = QSqlDatabase::addDatabase ( "QSQLITE" );
   db.setDatabaseName ( database_name() );
   if ( db.open() )
   {
     return successful();
   }
   return error();
 }
Exemplo n.º 4
0
int database_create_transaction_indexes(struct database* db)
{
    bson_t* keys;
    mongoc_index_opt_t opt;
    bson_error_t error;

    mongoc_collection_t* collection = mongoc_client_get_collection(db->client, database_name(db), "transactions");

    // transactions.hash
    {
        keys = bson_new();
        BSON_APPEND_INT32(keys, "hash", 1);

        mongoc_index_opt_init(&opt);
        opt.unique = 1;

        if(mongoc_collection_create_index(collection, keys, &opt, &error) == 0) {
            printf("index creation error (transaction.hash)\n");
        }

        bson_destroy(keys);
    }

    // (transaction.inputs.output_reference.hash, transaction.inputs.output_reference.index) [non-unique]
    {
        keys = bson_new();
        BSON_APPEND_INT32(keys, "inputs.output_reference.hash", 1);
        BSON_APPEND_INT32(keys, "inputs.output_reference.index", 1);

        mongoc_index_opt_init(&opt);
        opt.unique = 0;

        if(mongoc_collection_create_index(collection, keys, &opt, &error) == 0) {
            printf("index creation error (inputs.output_reference)\n");
        }

        bson_destroy(keys);
    }

    mongoc_collection_destroy(collection);
    return 0;
}
Exemplo n.º 5
0
int database_has_transaction(struct database* db, unsigned char const* hash)
{
    int result = 0;

    // TODO check cache
    // check db
    mongoc_collection_t* collection = mongoc_client_get_collection(db->client, database_name(db), "transactions");

    // Convert the transaction to a bson document
    bson_t* query = bson_new();

    // Set the hash
    BSON_APPEND_BINARY(query, "hash", BSON_SUBTYPE_BINARY, (uint8_t*)hash, 32);

    // Setup an empty projection so that the query returns less data
    bson_t* proj = bson_new();

    // Find
    mongoc_cursor_t* cursor = mongoc_collection_find(collection, MONGOC_QUERY_NONE, 0, 1, 0, query, proj, NULL);

    bson_error_t error;
    if(cursor == NULL || mongoc_cursor_error(cursor, &error)) {
        printf("MongoDB error: %s\n", (cursor == NULL) ? "NULL cursor" : error.message);
    }

    bson_t const* doc;
    if(mongoc_cursor_next(cursor, &doc) != 0) {
        result = 1;
    }

    mongoc_cursor_destroy(cursor);
    bson_destroy(proj);
    bson_destroy(query);
    mongoc_collection_destroy(collection);

    return result;
}
Exemplo n.º 6
0
int database_add_orphan_transaction(struct database* db, unsigned char const* hash, struct transaction const* tx)
{
    mongoc_collection_t* collection = mongoc_client_get_collection(db->client, database_name(db), "transactions");
    
    // Convert the transaction to a bson document
    bson_t* doc = bson_new();
    transaction_bson(tx, doc);

    // Set the hash
    BSON_APPEND_BINARY(doc, "hash", BSON_SUBTYPE_BINARY, (uint8_t*)hash, 32);

    // Give it a new id
    bson_oid_t oid;
    bson_oid_init(&oid, NULL);
    BSON_APPEND_OID(doc, "_id", &oid);

    // Orphan -> height = -1
    BSON_APPEND_INT32(doc, "height", -1);

#if 0
    // Print json
    char* str = bson_as_json(doc, NULL);
    printf("%s\n", str);
    bson_free(str);
#endif

    // Perform insert
    bson_error_t error;
    if(mongoc_collection_insert(collection, MONGOC_INSERT_NONE, doc, NULL, &error) == 0) {
        printf("MongoDB error: %s\n", error.message);
    }

    bson_destroy(doc);
    mongoc_collection_destroy(collection);
    return 0;
}
Exemplo n.º 7
0
void relations_convert_open(database db) {
/* relations_open
 * Load all of the relations in the specified database
 */
	boolean masterdb;
	DIR *directory;
	char dirpath[FILE_PATH_SIZE+1];
	char newdir[FILE_PATH_SIZE+1],ddname[FILE_PATH_SIZE+1];
	mode_t mode;
	tuple nt;
	relation ddrel;
	struct dirent *d;
	relation rel;

	masterdb=(strcmp(database_name(db),MASTER_DB_NAME)==0);

	leap_fprintf(stdout,"Converting database [%s] ",database_name(db));
	if (masterdb==TRUE) {
		leap_printf("(Master Database)\n");
	} else {
		leap_printf("(User Database)\n");
	}

	sprintf(dirpath,"%s%s",database_dir(db),LEAP_RELATION_DIR);
	directory=opendir(dirpath);
		
		if (directory!=NULL) {

			/* Create a backup directory for the old format
			 * relations.
			 */

			mode=sprintf(newdir,"%soldfmt",dirpath);
			mkdir(newdir,0777);
		
			d=readdir(directory);

			while (d!=NULL) {

#ifdef __MSDOS__
				/* See comment in util.c for list_source
				 * DOS filenames are always in capitals.
				 */
				downcase(d->d_name);
#endif

					if (strstr(d->d_name,LEAP_RELATION_EXT)!=NULL) {
						/* Read the relation from the disk */
						rel=relation_read(dirpath,d->d_name);
						/* Insert the relation into the database */
						relation_insert(db,rel);
					}

					d=readdir(directory);
				}		

			/* Close the directory */
			closedir(directory);
	}

	leap_fprintf(stdout,"Completed conversion of [%s]\n",database_name(db));
	
	leap_fprintf(stdout,"Updating [%s]...",LEAP_DD_RELATIONS);
	fflush(stdout);

	/* Open the leaprel database */
	sprintf(dirpath,"%s%s",database_dir(db),LEAP_RELATION_DIR);
	sprintf(ddname,"%s%s",LEAP_DD_RELATIONS,LEAP_NEW_RELATION_EXT);
	ddrel=relation_new_read(dirpath,ddname);

	/* Did the relation get returned? */
	if (ddrel!=NULL) {
	
		/* Prepare a tuple */
		nt=tuple_prepare(ddrel);
		
		/* Find the first relation in the database */
		rel=relation_findfirst(db);
		
		/* Whilst a relation is being returned */
		while( (rel!=NULL) && (strlen(relation_name(rel))>=0) ){

			/* TODO: Why does the relation name sometimes have nothing in it? */
		
			/* Populate the output tuple */
			
			/* Relation name */
			strcpy( tuple_d(nt,LEAP_DDA_RELATIONS_NAME_NO),relation_name(rel));
			
			/* Relation filename */
			sprintf(tuple_d(nt,LEAP_DDA_RELATIONS_FNAME_NO), "%s%s", relation_name(rel), LEAP_NEW_RELATION_EXT);
			
			/* Temporary status */
			if ( relation_temporary(rel) ) {
				strcpy( tuple_d(nt,LEAP_DDA_RELATIONS_TEMP_NO),TRUE_STRING);
			} else {
				strcpy( tuple_d(nt,LEAP_DDA_RELATIONS_TEMP_NO),FALSE_STRING);
			}

			/* Noattributes status */
			strcpy( tuple_d(nt,LEAP_DDA_RELATIONS_NOATTRIBS_NO),"1");
			
			/* Updated status */
			strcpy( tuple_d(nt,LEAP_DDA_RELATIONS_UPDATED_NO),FALSE_STRING);
			
			/* System relation status */			
			if ( relation_system(rel) ) {
				strcpy( tuple_d(nt,LEAP_DDA_RELATIONS_SYSTEM_NO),TRUE_STRING);
			} else {
				strcpy( tuple_d(nt,LEAP_DDA_RELATIONS_SYSTEM_NO),FALSE_STRING);
			}
		
			/* Write the tuple */
			(void)tuple_append(nt);
	
			/* Read the next relation */
			rel=relation_findnext(rel);
		}
		
		/* Dispose of the output tuple */
		tuple_dispose(&nt);
	} else {
		leap_fprintf(stderr,"\nERROR: System relation [%s] does not exist. See release NOTES\nin base directory!\n",
			LEAP_DD_RELATIONS);
		exit(1);
	}
	
	leap_fprintf(stdout,"Completed conversion.\n");
}
Exemplo n.º 8
0
void do_daemon() {
/* do_leap
 * Main LEAP daemon routine - Contains socket handler
 */
	char buffer[MAXIMUM_INPUT_STRING+1];
	char loginname[MAXIMUM_INPUT_STRING+1];
	char password[MAXIMUM_INPUT_STRING+1];
	char maincommand[MAXIMUM_INPUT_STRING+1];
	char tprompt[MAXIMUM_INPUT_STRING+1];
	char *result,*tresult,*plogin,*ppass;
	relation result_relation;
	int res,startscript=0;
	int serverSocket=0, on=0, port=0, status=0, childPid=0;
	struct hostent *hostPtr=NULL;
	char hostname[80]="";
	struct sockaddr_in serverName={0},clientName={0};
	struct linger linger={0};
	struct utsname sysinfo;
	int clientLength;
	tuple ctuple;

	clientLength=sizeof(clientName);

	tempdb=LEAPAPI_db_create(NULL,TEMPDB_NAME);
	res=relations_ddopen(tempdb);
	if (res!=RETURN_SUCCESS) {
		raise_error(ERROR_OPEN_DATABASE,FATAL,TEMPDB_NAME);		
	}

	/* Open the master database */
	master_db=LEAPAPI_db_create(NULL,MASTER_DB_NAME);
	res=relations_ddopen(master_db);
	if (res!=RETURN_SUCCESS) {
		raise_error(ERROR_OPEN_DATABASE,FATAL,MASTER_DB_NAME);		
	}

	if (strlen(dbtoopen)==0) {
		/* Open up the default user database */
		current_db=LEAPAPI_db_create(NULL,DEFAULT_DB);
	} else {
		current_db=LEAPAPI_db_create(NULL,dbtoopen);
	}

	res=relations_ddopen(current_db);
	if (res!=RETURN_SUCCESS) {
		raise_error(ERROR_OPEN_DATABASE,FATAL,database_name(current_db));		
	}
	
	set_variable(VAR_CURRENTDB,database_name(current_db));

	/* Check to see if the logins relation exists */
	result_relation=relation_find(master_db,LEAP_DD_LOGINS);	

	if (result_relation==NULL) {
		raise_error(ERROR_CANNOT_FIND_REL,NONFATAL,LEAP_DD_LOGINS);
		raise_message(MESSAGE,"Building %s",LEAP_DD_LOGINS);

        /* Build the leaplogins relation */
        sprintf(buffer,"(SUID,INTEGER,3),(NAME,string,25),(PASSWORD,string,25),(DEFAULTDB,string,25)");
        relation_insert(master_db,create_user_relation(master_db,buffer,LEAP_DD_LOGINS,FALSE,TRUE));

        vprocess_query(master_db,"add (%s) (%d,%s,%s,%s)",LEAP_DD_LOGINS,LEAP_SUID_DBA,LEAP_LOGIN_DBA,LEAP_PASS_DBA,MASTER_DB_NAME);
	} else {
		raise_message(MESSAGE,"Found %s!",LEAP_DD_LOGINS);
	}


	if (status_quiet!=TRUE) {
		raise_message(MESSAGE,"%s","Startup sequence initiated.");
	}

	terminate=FALSE;
	terminatenow=FALSE;

	if (status_quiet) {
			strcpy(current_prompt,"");
			set_prompt("");
	} else {
			strcpy(current_prompt,DEFAULT_PROMPT);
			set_prompt(DEFAULT_PROMPT);
	}

	if (configuration!=TRUE) {
		raise_message(MESSAGE,"Sourcing %s%s in %s",LEAP_STARTUP,LEAP_SOURCE_EXT,database_name(master_db));
		sprintf(buffer,"%s%s%s%s",database_dir(master_db),LEAP_SOURCE_DIR,LEAP_STARTUP,LEAP_SOURCE_EXT);
		assign_input_stream(buffer);
	} else {
		sprintf(buffer,"%s",configurationfile);
		assign_input_stream(buffer);
	}


	serverSocket=socket(PF_INET,SOCK_STREAM,0);

	if (serverSocket==-1) {
		raise_error(ERROR_SOCKETINIT,FATAL,"socket()");
	}

	on=1;

	status=setsockopt(serverSocket,SOL_SOCKET,SO_REUSEADDR,(const char *) &on,sizeof(on));

	if (status==-1) {
		raise_error(ERROR_SOCKETINIT,FATAL,"setsockopt(...,SO_REUSEADDR,...)");
	}
	
	linger.l_onoff=1;
	linger.l_linger=30;
	status=setsockopt(serverSocket,SOL_SOCKET,SO_LINGER,(const char *) &linger,sizeof(linger));
	if (status==-1) {
		raise_error(ERROR_SOCKETINIT,FATAL,"setsockopt(...,SO_LINGER,...)");
	}
		
	status=uname(&sysinfo);
	if (status==-1) {
		raise_error(ERROR_SOCKETINIT,FATAL,"uname");
	} else {
		strncpy(hostname,sysinfo.nodename,sizeof(hostname));
	}
		
	status=gethostname(hostname,sizeof(hostname));
	hostPtr=gethostbyname(hostname);

	if (hostPtr==NULL) {
		raise_error(ERROR_SOCKETINIT,FATAL,"gethostbyname");
	} 
	
	(void) memset(&serverName,0,sizeof(serverName));
	(void) memcpy(&serverName.sin_addr,hostPtr->h_addr,hostPtr->h_length);
	
	serverName.sin_family=AF_INET;
	serverName.sin_port=htons(LEAPD_PORT);
	status=bind(serverSocket,(struct sockaddr *) &serverName,sizeof(serverName));

	if (status<0) {
		raise_error(ERROR_SOCKETINIT,FATAL,"bind() - port %u - errno %u",LEAPD_PORT,errno);
	} else {
		raise_message(MESSAGE,"Daemon starting on machine %s, port %u",hostname,LEAPD_PORT);
	}

	status=listen(serverSocket,LEAPD_BACK_LOG);
	if (status==-1) {
		raise_error(ERROR_SOCKETINIT,FATAL,"listen()");
	}


	while (!terminatenow) {
			slaveSocket=accept(serverSocket,(struct sockaddr *) &clientName,&clientLength);

			if (slaveSocket==-1) {
				raise_error(ERROR_SOCKETINIT,FATAL,"accept()");
			}
				
			raise_message(MESSAGE,"Connection received from [%s]",inet_ntoa(clientName.sin_addr));

			raise_message(MESSAGE,"Authenication expected");

			strcpy(buffer,"Please authenticate yourself: ");
			write(slaveSocket,buffer,strlen(buffer));

			read(slaveSocket,loginname,MAXIMUM_INPUT_STRING);
			plogin=strtok(loginname,"\r\n");
			raise_message(MESSAGE,"Login [%s] connecting...",plogin);

			if (strcmp(plogin,"guest")==0) {
				strcpy(buffer,"Enter your e-mail address: ");
				write(slaveSocket,buffer,strlen(buffer));
			} else {
				strcpy(buffer,"Password: "******"project (select (%s) (%s='%s')) (%s)",LEAP_DD_LOGINS,LEAP_DDA_LOGINS_NAME,plogin,LEAP_DDA_LOGINS_PASSWORD);
			result_relation=process_query(master_db,buffer);

			status=read(slaveSocket,password,MAXIMUM_INPUT_STRING);
			ppass=strtok(password,"\r\n");

			if ((ppass!=NULL) && (status==2)) {
				*ppass='******';
			}

			ctuple=tuple_readfirst(result_relation,TUPLE_BUILD,NULL);
			if (ctuple!=NULL) {
				tuple_to_string(ctuple,buffer);
				raise_message(MESSAGE,"Password expected [%s]",buffer);
				raise_message(MESSAGE,"Password received [%s]",ppass);
			} else {
				if (strcmp(plogin,"guest")==0) {
					raise_message(MESSAGE,"Guest ID [%s]",ppass);
				} else {
					raise_message(MESSAGE,"No login [%s] exists!",plogin);
				}
			}
	
			if (((strcmp(plogin,"guest")==0))||(strcmp(buffer,ppass)==0)) {
					raise_message(MESSAGE,"Login [%s] validated!",plogin); 
					/* Enable daemon on - this will send io to client */
					status_daemon=TRUE;
				
					strcpy(buffer,"version");
					result_relation=process_query(current_db,buffer);

					/* Ok, socket is initialised! */
					while (!terminate) {

						write(slaveSocket,DEFAULT_PROMPT,sizeof(DEFAULT_PROMPT));
						status=read(slaveSocket,buffer,MAXIMUM_INPUT_STRING);
						/* Null terminate reqd....*/
						
						result=strtok(buffer,"\r\n");
						
						status_daemon=FALSE;
						raise_message(MESSAGE,"received: %s",result);
						status_daemon=TRUE;

						result_relation=process_query(current_db,result);

					}
					/* Disable daemon */
					status_daemon=FALSE;
			} else {
				raise_message(MESSAGE,"Invalid password for login [%s]",plogin);
			}

			/* Reset terminate - one client has disconnected */
			terminate=FALSE;

			raise_message(MESSAGE,"Connection closed");
			close(slaveSocket);
	}

	if (!status_quiet) { raise_message(MESSAGE,"Closing [%s] database.",database_name(current_db)); }
	
	relations_dispose_all(current_db);

	LEAPAPI_db_destroy(&current_db);

	raise_event(EVENT,"[current_db] closed.");

	if (!status_quiet) { raise_message(MESSAGE,"Closing [%s] database.",database_name(master_db)); }

	relations_dispose_all(master_db);
	
	LEAPAPI_db_destroy(&master_db);

	raise_event(EVENT,"[master_db] closed.");

	if (!status_quiet) { raise_message(MESSAGE,"Closing [%s] database.",database_name(tempdb)); }

	relations_dispose_all(tempdb);
	
	LEAPAPI_db_destroy(&tempdb);

	raise_event(EVENT,"[tempdb] closed.");
}