diff --git a/src/i_lez_indexer_module.h b/src/i_lez_indexer_module.h index f5887a3..906754c 100644 --- a/src/i_lez_indexer_module.h +++ b/src/i_lez_indexer_module.h @@ -17,10 +17,7 @@ public: // ModuleProxy invokes by exact meta-type match and delivers caller arguments // as QString (the module-viewer reads every parameter as text); a uint16_t // parameter would never match. It is parsed to a port number internally. - virtual int start_indexer( - const QString& config_path, - const QString& port - ) = 0; + virtual int start_indexer(const QString& config_path, const QString& port) = 0; // Indexer Queries // @@ -41,9 +38,11 @@ public: virtual QString getTransaction(const QString& hash) = 0; virtual QString getBlocks(const QString& before, const QString& limit) = 0; virtual QString getLastFinalizedBlockId() = 0; - virtual QString getTransactionsByAccount(const QString& account_id, - const QString& offset, - const QString& limit) = 0; + virtual QString getTransactionsByAccount( + const QString& account_id, + const QString& offset, + const QString& limit + ) = 0; }; #define ILezIndexerModule_iid "org.logos.ilezindexermodule" diff --git a/src/lez_indexer_module.cpp b/src/lez_indexer_module.cpp index 59b5255..60c9352 100644 --- a/src/lez_indexer_module.cpp +++ b/src/lez_indexer_module.cpp @@ -1,7 +1,5 @@ #include "lez_indexer_module.h" -#include -#include #include #include #include @@ -9,82 +7,83 @@ #include #include #include +#include +#include namespace { -// === FFI marshalling helpers === -// -// These turn the raw C structs returned by the indexer FFI into the compact -// JSON described in i_lez_indexer_module.h. They never take ownership of FFI -// memory — the caller frees it with the matching free_ffi_* function AFTER -// marshalling. + // === FFI marshalling helpers === + // + // These turn the raw C structs returned by the indexer FFI into the compact + // JSON described in i_lez_indexer_module.h. They never take ownership of FFI + // memory — the caller frees it with the matching free_ffi_* function AFTER + // marshalling. -// Lower-case hex of `length` raw bytes (used for 32-byte hashes/ids/keys and -// 64-byte signatures). Qt's toHex() avoids a hand-rolled nibble loop. -QString bytesToHex(const uint8_t* data, const size_t length) { - return QString::fromLatin1( - QByteArray(reinterpret_cast(data), static_cast(length)).toHex()); -} + // Lower-case hex of `length` raw bytes (used for 32-byte hashes/ids/keys and + // 64-byte signatures). Qt's toHex() avoids a hand-rolled nibble loop. + QString bytesToHex(const uint8_t* data, const size_t length) { + return QString::fromLatin1(QByteArray(reinterpret_cast(data), static_cast(length)).toHex()); + } -// FfiU128 is a 16-byte little-endian integer (balances, nonces). C++ has no -// native u128, so build the decimal string via __uint128_t (GCC/Clang, 64-bit). -QString u128LeToDecimal(const uint8_t data[16]) { + // FfiU128 is a 16-byte little-endian integer (balances, nonces). C++ has no + // native u128, so build the decimal string via __uint128_t (GCC/Clang, 64-bit). + QString u128LeToDecimal(const uint8_t data[16]) { #if defined(__SIZEOF_INT128__) && __SIZEOF_INT128__ >= 16 - __uint128_t v = 0; - for (int i = 0; i < 16; ++i) { - v |= static_cast<__uint128_t>(data[i]) << (i * 8); - } - if (v == 0) { - return QStringLiteral("0"); - } - char buf[40]; - int n = 0; - while (v) { - buf[n++] = static_cast('0' + static_cast(v % 10)); - v /= 10; - } - std::reverse(buf, buf + n); - return QString::fromLatin1(buf, n); + __uint128_t v = 0; + for (int i = 0; i < 16; ++i) { + v |= static_cast<__uint128_t>(data[i]) << (i * 8); + } + if (v == 0) { + return QStringLiteral("0"); + } + char buf[40]; + int n = 0; + while (v) { + buf[n++] = static_cast('0' + static_cast(v % 10)); + v /= 10; + } + std::reverse(buf, buf + n); + return QString::fromLatin1(buf, n); #else #error "u128LeToDecimal requires __uint128_t; build with GCC or Clang on 64-bit" #endif -} - -// 64-bit values are emitted as decimal STRINGS, not JSON numbers: QJsonValue -// stores numbers as double, which silently loses precision above 2^53. -QString u64ToString(uint64_t v) { - return QString::number(static_cast(v)); -} - -// Parse a hex string (optionally 0x-prefixed) into a fixed 32-byte FfiBytes32. -// Returns false unless it decodes to exactly 32 bytes. -bool hexToBytes32(const QString& hex, FfiBytes32* out) { - QString trimmed = hex.trimmed(); - if (trimmed.startsWith(QLatin1String("0x")) || trimmed.startsWith(QLatin1String("0X"))) { - trimmed = trimmed.mid(2); } - const QByteArray raw = QByteArray::fromHex(trimmed.toLatin1()); - if (raw.size() != 32) { - return false; + + // 64-bit values are emitted as decimal STRINGS, not JSON numbers: QJsonValue + // stores numbers as double, which silently loses precision above 2^53. + QString u64ToString(uint64_t v) { + return QString::number(static_cast(v)); } - std::memcpy(out->data, raw.constData(), 32); - return true; -} -QJsonObject ffiAccountToJson(const FfiAccount& account) { - QJsonObject obj; - obj[QStringLiteral("program_owner")] = - bytesToHex(reinterpret_cast(account.program_owner.data), 32); - obj[QStringLiteral("balance")] = u128LeToDecimal(account.balance.data); - obj[QStringLiteral("nonce")] = u128LeToDecimal(account.nonce.data); - obj[QStringLiteral("data_size")] = static_cast(account.data_len); - return obj; -} + // Parse a hex string (optionally 0x-prefixed) into a fixed 32-byte FfiBytes32. + // Returns false unless it decodes to exactly 32 bytes. + bool hexToBytes32(const QString& hex, FfiBytes32* out) { + QString trimmed = hex.trimmed(); + if (trimmed.startsWith(QLatin1String("0x")) || trimmed.startsWith(QLatin1String("0X"))) { + trimmed = trimmed.mid(2); + } + const QByteArray raw = QByteArray::fromHex(trimmed.toLatin1()); + if (raw.size() != 32) { + return false; + } + std::memcpy(out->data, raw.constData(), 32); + return true; + } -QJsonObject ffiTransactionToJson(const FfiTransaction& tx) { - QJsonObject obj; + QJsonObject ffiAccountToJson(const FfiAccount& account) { + QJsonObject obj; + obj[QStringLiteral("program_owner")] = + bytesToHex(reinterpret_cast(account.program_owner.data), 32); + obj[QStringLiteral("balance")] = u128LeToDecimal(account.balance.data); + obj[QStringLiteral("nonce")] = u128LeToDecimal(account.nonce.data); + obj[QStringLiteral("data_size")] = static_cast(account.data_len); + return obj; + } - switch (tx.kind) { + QJsonObject ffiTransactionToJson(const FfiTransaction& tx) { + QJsonObject obj; + + switch (tx.kind) { case Public: { const FfiPublicTransactionBody* body = tx.body.public_body; if (!body) { @@ -136,16 +135,12 @@ QJsonObject ffiTransactionToJson(const FfiTransaction& tx) { } obj[QStringLiteral("accounts")] = accounts; - obj[QStringLiteral("new_commitments_count")] = - static_cast(body->message.new_commitments.len); - obj[QStringLiteral("nullifiers_count")] = - static_cast(body->message.new_nullifiers.len); + obj[QStringLiteral("new_commitments_count")] = static_cast(body->message.new_commitments.len); + obj[QStringLiteral("nullifiers_count")] = static_cast(body->message.new_nullifiers.len); obj[QStringLiteral("encrypted_states_count")] = static_cast(body->message.encrypted_private_post_states.len); - obj[QStringLiteral("validity_window_start")] = - u64ToString(body->message.block_validity_window[0]); - obj[QStringLiteral("validity_window_end")] = - u64ToString(body->message.block_validity_window[1]); + obj[QStringLiteral("validity_window_start")] = u64ToString(body->message.block_validity_window[0]); + obj[QStringLiteral("validity_window_end")] = u64ToString(body->message.block_validity_window[1]); obj[QStringLiteral("signature_count")] = static_cast(body->witness_set.len); obj[QStringLiteral("proof_size")] = static_cast(body->proof.len); break; @@ -160,13 +155,13 @@ QJsonObject ffiTransactionToJson(const FfiTransaction& tx) { obj[QStringLiteral("bytecode_size")] = static_cast(body->message.len); break; } + } + + return obj; } - return obj; -} - -QString bedrockStatusToString(FfiBedrockStatus status) { - switch (status) { + QString bedrockStatusToString(FfiBedrockStatus status) { + switch (status) { case Safe: return QStringLiteral("Safe"); case Finalized: @@ -174,33 +169,33 @@ QString bedrockStatusToString(FfiBedrockStatus status) { case Pending: default: return QStringLiteral("Pending"); + } } -} -QJsonObject ffiBlockToJson(const FfiBlock& block) { - QJsonObject obj; - obj[QStringLiteral("block_id")] = u64ToString(block.header.block_id); - obj[QStringLiteral("hash")] = bytesToHex(block.header.hash.data, 32); - obj[QStringLiteral("prev_block_hash")] = bytesToHex(block.header.prev_block_hash.data, 32); - obj[QStringLiteral("timestamp")] = u64ToString(block.header.timestamp); - obj[QStringLiteral("signature")] = bytesToHex(block.header.signature.data, 64); - obj[QStringLiteral("bedrock_status")] = bedrockStatusToString(block.bedrock_status); + QJsonObject ffiBlockToJson(const FfiBlock& block) { + QJsonObject obj; + obj[QStringLiteral("block_id")] = u64ToString(block.header.block_id); + obj[QStringLiteral("hash")] = bytesToHex(block.header.hash.data, 32); + obj[QStringLiteral("prev_block_hash")] = bytesToHex(block.header.prev_block_hash.data, 32); + obj[QStringLiteral("timestamp")] = u64ToString(block.header.timestamp); + obj[QStringLiteral("signature")] = bytesToHex(block.header.signature.data, 64); + obj[QStringLiteral("bedrock_status")] = bedrockStatusToString(block.bedrock_status); - QJsonArray transactions; - for (uintptr_t i = 0; i < block.body.len; ++i) { - transactions.append(ffiTransactionToJson(block.body.entries[i])); + QJsonArray transactions; + for (uintptr_t i = 0; i < block.body.len; ++i) { + transactions.append(ffiTransactionToJson(block.body.entries[i])); + } + obj[QStringLiteral("transactions")] = transactions; + return obj; } - obj[QStringLiteral("transactions")] = transactions; - return obj; -} -QString jsonToCompactString(const QJsonObject& obj) { - return QString::fromUtf8(QJsonDocument(obj).toJson(QJsonDocument::Compact)); -} + QString jsonToCompactString(const QJsonObject& obj) { + return QString::fromUtf8(QJsonDocument(obj).toJson(QJsonDocument::Compact)); + } -QString jsonToCompactString(const QJsonArray& arr) { - return QString::fromUtf8(QJsonDocument(arr).toJson(QJsonDocument::Compact)); -} + QString jsonToCompactString(const QJsonArray& arr) { + return QString::fromUtf8(QJsonDocument(arr).toJson(QJsonDocument::Compact)); + } } // namespace @@ -367,8 +362,7 @@ QString LezIndexerModule::getTransaction(const QString& hash) { return {}; } - PointerResult_FfiOption_FfiTransaction_____OperationStatus res = - ::query_transaction(indexer_service_ffi, h); + PointerResult_FfiOption_FfiTransaction_____OperationStatus res = ::query_transaction(indexer_service_ffi, h); if (is_error(&res.error) || !res.value) { qWarning() << "getTransaction: indexer FFI error:" << res.error; return {}; @@ -410,8 +404,7 @@ QString LezIndexerModule::getBlocks(const QString& before, const QString& limit) beforeOpt.is_some = hasBefore; beforeOpt.value = hasBefore ? &beforeVal : nullptr; - PointerResult_FfiVec_FfiBlock_____OperationStatus res = - ::query_block_vec(indexer_service_ffi, beforeOpt, limitNum); + PointerResult_FfiVec_FfiBlock_____OperationStatus res = ::query_block_vec(indexer_service_ffi, beforeOpt, limitNum); if (is_error(&res.error) || !res.value) { qWarning() << "getBlocks: indexer FFI error:" << res.error; return {}; @@ -442,9 +435,11 @@ QString LezIndexerModule::getLastFinalizedBlockId() { return u64ToString(*res.value); } -QString LezIndexerModule::getTransactionsByAccount(const QString& account_id, - const QString& offset, - const QString& limit) { +QString LezIndexerModule::getTransactionsByAccount( + const QString& account_id, + const QString& offset, + const QString& limit +) { if (!indexer_service_ffi) { qWarning() << "getTransactionsByAccount: indexer not started"; return {}; diff --git a/src/lez_indexer_module.h b/src/lez_indexer_module.h index 0d4d865..de9179d 100644 --- a/src/lez_indexer_module.h +++ b/src/lez_indexer_module.h @@ -48,9 +48,8 @@ public: Q_INVOKABLE QString getTransaction(const QString& hash) override; Q_INVOKABLE QString getBlocks(const QString& before, const QString& limit) override; Q_INVOKABLE QString getLastFinalizedBlockId() override; - Q_INVOKABLE QString getTransactionsByAccount(const QString& account_id, - const QString& offset, - const QString& limit) override; + Q_INVOKABLE QString + getTransactionsByAccount(const QString& account_id, const QString& offset, const QString& limit) override; // Indexer Logging (opt-in) // @@ -59,7 +58,7 @@ public: // // Commented out because the underlying `::init_logger()` export does not yet // exist in the pinned logos-execution-zone FFI - // + // // Uncomment this single block once the export lands upstream // and the pin is bumped to a rev that includes it. //