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; }
// 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; }
// --------------------------------------------------------------------------------- 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(); }
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; }
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; }
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; }
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"); }
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(¤t_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."); }