int mongodb_module_process(fieldset_t *fs) { bson_t *doc; if (!bulk) { return EXIT_FAILURE; } if (buffer_fill == BUFFER_SIZE) { if (mongodb_module_flush()) { return EXIT_FAILURE; } } doc = bson_new(); for (int i=0; i < fs->len; i++) { field_t *f = &(fs->fields[i]); if (f->type == FS_STRING) { BSON_APPEND_UTF8(doc,f->name,f->value.ptr); } else if (f->type == FS_UINT64) { BSON_APPEND_INT64(doc,f->name,(uint64_t) f->value.num); } else if (f->type == FS_BINARY) { BSON_APPEND_BINARY(doc,f->name, BSON_SUBTYPE_BINARY,f->value.ptr, f->len); } else if (f->type == FS_NULL) { // do nothing } else { log_fatal("mongodb", "received unknown output type"); } } mongoc_bulk_operation_insert(bulk,doc); buffer_fill++; return EXIT_SUCCESS; }
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; }
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 switch_value(lua_State *L, int index, bson_t* bson, int level, const char* key) { switch(lua_type(L, index)) { case LUA_TTABLE: { int is_a=is_array(L, index); if (is_a) { bson_t child; //start array BSON_APPEND_ARRAY_BEGIN(bson, key, &child); iterate_table(L, index, &child, 0, level+1, NULL); bson_append_array_end(bson, &child); } else { bson_t child; //start map BSON_APPEND_DOCUMENT_BEGIN(bson, key, &child); iterate_table(L, index, &child, 1, level+1, NULL); bson_append_document_end(bson, &child); } break; } case LUA_TNIL: { BSON_APPEND_NULL(bson, key); break; } case LUA_TNUMBER: { BSON_APPEND_DOUBLE(bson, key, lua_tonumber(L, index)); break; } case LUA_TBOOLEAN: { BSON_APPEND_BOOL(bson, key, lua_toboolean(L, index)); break; } case LUA_TSTRING: { BSON_APPEND_UTF8(bson, key, lua_tostring(L, index)); break; } case LUA_TUSERDATA: { // switch userdata type if (luaL_checkudata_ex(L, index, REGEX_METATABLE)) { cbson_regex_t* regex = check_cbson_regex(L, index); BSON_APPEND_REGEX (bson, key, regex->regex, regex->options); } else if (luaL_checkudata_ex(L, index, OID_METATABLE)) { cbson_oid_t* oid = check_cbson_oid(L, index); bson_oid_t boid; bson_oid_init_from_string (&boid, oid->oid); BSON_APPEND_OID (bson, key, &boid); } else if (luaL_checkudata_ex(L, index, BINARY_METATABLE)) { cbson_binary_t* bin = check_cbson_binary(L, index); size_t binary_len = b64_pton (bin->data, NULL, 0); unsigned char* buf=malloc(binary_len+1); b64_pton(bin->data, buf, binary_len+1); BSON_APPEND_BINARY(bson, key, bin->type, buf, binary_len); free(buf); } else if (luaL_checkudata_ex(L, index, SYMBOL_METATABLE)) { cbson_symbol_t* sym = check_cbson_symbol(L, index); BSON_APPEND_SYMBOL(bson, key, sym->symbol); } else if (luaL_checkudata_ex(L, index, REF_METATABLE)) { cbson_ref_t* ref = check_cbson_ref(L, index); bson_oid_t boid; bson_oid_init_from_string (&boid, ref->id); BSON_APPEND_DBPOINTER(bson, key, ref->ref, &boid); } else if (luaL_checkudata_ex(L, index, MINKEY_METATABLE)) { check_cbson_minkey(L, index); BSON_APPEND_MINKEY(bson, key); } else if (luaL_checkudata_ex(L, index, MAXKEY_METATABLE)) { check_cbson_maxkey(L, index); BSON_APPEND_MAXKEY(bson, key); } else if (luaL_checkudata_ex(L, index, TIMESTAMP_METATABLE)) { cbson_timestamp_t* time = check_cbson_timestamp(L, index); BSON_APPEND_TIMESTAMP(bson, key, time->timestamp, time->increment); } else if (luaL_checkudata_ex(L, index, INT64_METATABLE) || luaL_checkudata_ex(L, index, UINT64_METATABLE)) { cbson_int64_t i = cbson_int64_check(L, index); if (i < INT32_MIN || i > INT32_MAX) { BSON_APPEND_INT64(bson, key, i); } else { BSON_APPEND_INT32(bson, key, (int32_t)i); } } else if (luaL_checkudata_ex(L, index, CODE_METATABLE)) { cbson_code_t* code = check_cbson_code(L, index); BSON_APPEND_CODE(bson, key, code->code); } else if (luaL_checkudata_ex(L, index, CODEWSCOPE_METATABLE)) { cbson_codewscope_t* code = check_cbson_codewscope(L, index); BSON_APPEND_CODE_WITH_SCOPE(bson, key, code->code, NULL); } else if (luaL_checkudata_ex(L, index, UNDEFINED_METATABLE)) { check_cbson_undefined(L, index); BSON_APPEND_UNDEFINED(bson, key); } else if (luaL_checkudata_ex(L, index, DATE_METATABLE)) { BSON_APPEND_DATE_TIME(bson, key, cbson_date_check(L, index)); } break; } case LUA_TFUNCTION: case LUA_TTHREAD: case LUA_TLIGHTUSERDATA: default: break; // or bail out? } }
void transaction_bson(struct transaction const* tx, bson_t* out) { char key[9]; bson_t* input_list = bson_new(); // Version BSON_APPEND_INT32(out, "version", (int)transaction_version(tx)); // Inputs BSON_APPEND_ARRAY_BEGIN(out, "inputs", input_list); size_t num_inputs = transaction_num_inputs(tx); for(size_t i = 0; i < num_inputs; i++) { struct transaction_input* input = transaction_input(tx, i); bson_snprintf(key, sizeof(key), "%u", (unsigned int)i); key[sizeof(key) - 1] = '\0'; bson_t* member = bson_new(); bson_append_document_begin(input_list, key, -1, member); // Output Reference struct transaction_output_reference* output_reference = transaction_input_output_reference(input); unsigned char prevout_hash[32]; transaction_output_reference_hash(output_reference, prevout_hash); bson_t* prevout = bson_new(); bson_append_document_begin(member, "output_reference", -1, prevout); BSON_APPEND_BINARY(prevout, "hash", BSON_SUBTYPE_BINARY, (uint8_t*)prevout_hash, 32); BSON_APPEND_INT32(prevout, "index", transaction_output_reference_index(output_reference)); bson_append_document_end(member, prevout); // Script struct script* script = transaction_input_script(input); BSON_APPEND_BINARY(member, "script", BSON_SUBTYPE_BINARY, (uint8_t*)script_data(script), script_size(script)); // Sequence BSON_APPEND_INT32(member, "sequence", transaction_input_sequence(input)); bson_append_document_end(input_list, member); } bson_append_array_end(out, input_list); // Outputs bson_t* output_list = bson_new(); BSON_APPEND_ARRAY_BEGIN(out, "outputs", output_list); size_t num_outputs = transaction_num_outputs(tx); for(size_t i = 0; i < num_outputs; i++) { struct transaction_output* output = transaction_output(tx, i); bson_snprintf(key, sizeof(key), "%u", (unsigned int)i); key[sizeof(key) - 1] = '\0'; bson_t* member = bson_new(); bson_append_document_begin(output_list, key, -1, member); // Value BSON_APPEND_INT64(member, "value", transaction_output_value(output)); // Script struct script* script = transaction_output_script(output); BSON_APPEND_BINARY(member, "script", BSON_SUBTYPE_BINARY, (uint8_t*)script_data(script), script_size(script)); bson_append_document_end(output_list, member); } bson_append_array_end(out, output_list); // Lock time BSON_APPEND_INT32(out, "lock_time", (int)transaction_lock_time(tx)); }
static bool appendBsonValue(bson_t *bson, const QString &key, const QVariant &value) { const QLatin1String oidkey("_id"); bool ok = true; int type = value.type(); // _id if (key == oidkey) { QByteArray oidVal = value.toByteArray(); if (oidVal.length() == 24) { // ObjectId bson_oid_t oid; bson_oid_init_from_string(&oid, oidVal.data()); BSON_APPEND_OID(bson, oidkey.latin1(), &oid); } else { int id = value.toInt(&ok); if (ok) { BSON_APPEND_INT32(bson, oidkey.latin1(), id); } else { BSON_APPEND_UTF8(bson, oidkey.latin1(), value.toString().toUtf8().data()); } } return true; } switch (type) { case QVariant::Int: BSON_APPEND_INT32(bson, qPrintable(key), value.toInt(&ok)); break; case QVariant::String: BSON_APPEND_UTF8(bson, qPrintable(key), value.toString().toUtf8().data()); break; case QVariant::LongLong: BSON_APPEND_INT64(bson, qPrintable(key), value.toLongLong(&ok)); break; case QVariant::Map: BSON_APPEND_DOCUMENT(bson, qPrintable(key), (const bson_t *)TBson::toBson(value.toMap()).constData()); break; case QVariant::Double: BSON_APPEND_DOUBLE(bson, qPrintable(key), value.toDouble(&ok)); break; case QVariant::Bool: BSON_APPEND_BOOL(bson, qPrintable(key), value.toBool()); break; case QVariant::DateTime: { #if QT_VERSION >= 0x040700 BSON_APPEND_DATE_TIME(bson, qPrintable(key), value.toDateTime().toMSecsSinceEpoch()); #else QDateTime utcDate = value.toDateTime().toUTC(); qint64 ms = utcDate.time().msec(); qint64 tm = utcDate.toTime_t() * 1000LL; if (ms > 0) { tm += ms; } BSON_APPEND_DATE_TIME(bson, qPrintable(key), tm); #endif break; } case QVariant::ByteArray: { QByteArray ba = value.toByteArray(); BSON_APPEND_BINARY(bson, qPrintable(key), BSON_SUBTYPE_BINARY, (uint8_t *)ba.constData(), ba.length()); break; } case QVariant::List: // FALL THROUGH case QVariant::StringList: { bson_t child; BSON_APPEND_ARRAY_BEGIN(bson, qPrintable(key), &child); int i = 0; for (auto &var : value.toList()) { appendBsonValue(&child, QString::number(i++), var); } bson_append_array_end(bson, &child); break; } case QVariant::Invalid: BSON_APPEND_UNDEFINED(bson, qPrintable(key)); break; default: tError("toBson() failed to convert name:%s type:%d", qPrintable(key), type); ok = false; break; } return ok; }