ESP32: сохранять полный текст ошибки регистрации

This commit is contained in:
AidarKC 2026-06-13 00:24:42 +04:00
parent 436e1f0c53
commit 04252e006b
3 changed files with 107 additions and 9 deletions

View File

@ -0,0 +1,26 @@
# ESP32 полный текст ошибки регистрации Solana
- статус: `pending`
## Что сделано
- Локальные правки Solana-программ для диагностических `failed at ...` логов откатены.
- В основном ESP32-скетче сохранение последней ошибки регистрации переведено на полный текст RPC-диагностики.
- В `details` теперь сохраняются полные payload:
- `send_transaction_payload`
- `simulate_payload`
- Длинный текст ошибки сохраняется в `Preferences` по частям, чтобы не теряться из-за лимита одной строки.
- Чтение по USB-команде `last_error` / `last_diag` / `reg_diag` выводит сохранённый текст целиком.
## Что проверять
1. Запустить регистрацию на устройстве до ошибки.
2. По USB отправить `last_error`.
3. Проверить, что в ответе есть полный JSON/текст `sendTransaction` и `simulateTransaction`, а не только короткий summary.
4. Убедиться, что текст после перезагрузки устройства остаётся доступным через ту же команду.
## Ожидаемый результат
- Последняя ошибка регистрации читается по USB почти целиком.
- Если Solana уже вернула строку с местом падения, она не теряется из-за агрессивного обрезания на ESP32.

View File

@ -375,6 +375,7 @@ static bool loadUsersEconomyConfigState(const String &economyConfigAddress,
static bool loadAccountOwner(const String &address, String &ownerOut, bool &existsOut, String &messageOut); static bool loadAccountOwner(const String &address, String &ownerOut, bool &existsOut, String &messageOut);
static bool extractRpcErrorSummary(const String &payload, String &messageOut); static bool extractRpcErrorSummary(const String &payload, String &messageOut);
static String compactRpcLogs(const String &payload, int maxLines = 3); static String compactRpcLogs(const String &payload, int maxLines = 3);
static bool simulateTransactionPayload(const String &txBase64, String &payloadOut);
static bool simulateTransactionForError(const String &txBase64, String &messageOut); static bool simulateTransactionForError(const String &txBase64, String &messageOut);
static std::vector<uint8_t> buildLastBlockStateBytes(const String &login, const String &blockchainName); static std::vector<uint8_t> buildLastBlockStateBytes(const String &login, const String &blockchainName);
static std::vector<uint8_t> buildUnsignedCreateRecord( static std::vector<uint8_t> buildUnsignedCreateRecord(
@ -411,6 +412,9 @@ static bool signMessageEd25519(const std::vector<uint8_t> &message, const uint8_
static String encodeTransactionBase64(const uint8_t signature[64], const std::vector<uint8_t> &message); static String encodeTransactionBase64(const uint8_t signature[64], const std::vector<uint8_t> &message);
static bool awaitTransactionConfirmation(const String &signatureB58, String &messageOut); static bool awaitTransactionConfirmation(const String &signatureB58, String &messageOut);
static bool registerHomeserverOnSolana(String &messageOut); static bool registerHomeserverOnSolana(String &messageOut);
static void loadRegisterDiagDetailsFromPrefs();
static void saveRegisterDiagDetailsToPrefs(const String &details);
static void clearRegisterDiagDetailsFromPrefs();
static void saveRegisterDiag(const String &status, const String &summary, const String &details); static void saveRegisterDiag(const String &status, const String &summary, const String &details);
static void printRegisterDiagToSerial(); static void printRegisterDiagToSerial();
static void clearRegisterDiag(); static void clearRegisterDiag();
@ -1471,9 +1475,14 @@ static bool extractRpcErrorSummary(const String &payload, String &messageOut) {
return !messageOut.isEmpty(); return !messageOut.isEmpty();
} }
static bool simulateTransactionPayload(const String &txBase64, String &payloadOut) {
payloadOut = "";
return rpcCallSolana("simulateTransaction", "[\"" + txBase64 + "\",{\"encoding\":\"base64\",\"sigVerify\":true,\"commitment\":\"processed\"}]", payloadOut);
}
static bool simulateTransactionForError(const String &txBase64, String &messageOut) { static bool simulateTransactionForError(const String &txBase64, String &messageOut) {
String payload; String payload;
if (!rpcCallSolana("simulateTransaction", "[\"" + txBase64 + "\",{\"encoding\":\"base64\",\"sigVerify\":true,\"commitment\":\"processed\"}]", payload)) { if (!simulateTransactionPayload(txBase64, payload)) {
return false; return false;
} }
return extractRpcErrorSummary(payload, messageOut); return extractRpcErrorSummary(payload, messageOut);
@ -1764,13 +1773,21 @@ static bool registerHomeserverOnSolana(String &messageOut) {
if (!extractRpcErrorSummary(payload, messageOut)) { if (!extractRpcErrorSummary(payload, messageOut)) {
messageOut = "RPC returned sendTransaction error"; messageOut = "RPC returned sendTransaction error";
} }
diagDetails += "send_transaction_payload<<\n";
diagDetails += payload;
diagDetails += "\n>>send_transaction_payload\n";
String simulated; String simulated;
if (simulateTransactionForError(txBase64, simulated)) { String simulatedPayload;
if (simulateTransactionPayload(txBase64, simulatedPayload)) {
extractRpcErrorSummary(simulatedPayload, simulated);
if (messageOut.isEmpty()) { if (messageOut.isEmpty()) {
messageOut = simulated; messageOut = simulated;
} else if (messageOut.indexOf(simulated) < 0) { } else if (messageOut.indexOf(simulated) < 0) {
messageOut += " | simulate: " + simulated; messageOut += " | simulate: " + simulated;
} }
diagDetails += "simulate_payload<<\n";
diagDetails += simulatedPayload;
diagDetails += "\n>>simulate_payload\n";
} }
diagDetails += String("send_transaction_error=") + messageOut + "\n"; diagDetails += String("send_transaction_error=") + messageOut + "\n";
return failWithDiag(messageOut); return failWithDiag(messageOut);
@ -2721,7 +2738,7 @@ static void loadPrefs() {
gRegistrationSignature = gPrefs.getString("registration_sig", ""); gRegistrationSignature = gPrefs.getString("registration_sig", "");
gLastRegisterDiagStatus = gPrefs.getString("reg_diag_status", "none"); gLastRegisterDiagStatus = gPrefs.getString("reg_diag_status", "none");
gLastRegisterDiagSummary = gPrefs.getString("reg_diag_summary", ""); gLastRegisterDiagSummary = gPrefs.getString("reg_diag_summary", "");
gLastRegisterDiagDetails = gPrefs.getString("reg_diag_details", ""); loadRegisterDiagDetailsFromPrefs();
gLastRegisterDiagTime = gPrefs.getString("reg_diag_time", ""); gLastRegisterDiagTime = gPrefs.getString("reg_diag_time", "");
gBalanceStatusMessage = gDevicePubB58.isEmpty() ? "Balance: secret not set" : "Balance: tap to load"; gBalanceStatusMessage = gDevicePubB58.isEmpty() ? "Balance: secret not set" : "Balance: tap to load";
gAccountCheckPending = true; gAccountCheckPending = true;
@ -2837,15 +2854,70 @@ static String wifiHomeSummary() {
return String("Wi-Fi (") + gWifiSavedSsid + ") disconnected"; return String("Wi-Fi (") + gWifiSavedSsid + ") disconnected";
} }
static void loadRegisterDiagDetailsFromPrefs() {
gLastRegisterDiagDetails = "";
int chunks = gPrefs.getInt("rddn", 0);
if (chunks <= 0) {
gLastRegisterDiagDetails = gPrefs.getString("reg_diag_details", "");
return;
}
if (chunks > 12) {
chunks = 12;
}
for (int i = 0; i < chunks; ++i) {
String key = String("rdd") + i;
gLastRegisterDiagDetails += gPrefs.getString(key.c_str(), "");
}
}
static void saveRegisterDiagDetailsToPrefs(const String &details) {
const int chunkSize = 1400;
const int maxChunks = 12;
gPrefs.remove("reg_diag_details");
for (int i = 0; i < maxChunks; ++i) {
String key = String("rdd") + i;
gPrefs.remove(key.c_str());
}
String stored = details;
int requiredChunks = (stored.length() + chunkSize - 1) / chunkSize;
if (requiredChunks > maxChunks) {
int maxLen = chunkSize * maxChunks;
stored = stored.substring(0, maxLen);
stored += "\n[truncated in NVS]\n";
requiredChunks = (stored.length() + chunkSize - 1) / chunkSize;
if (requiredChunks > maxChunks) {
stored = stored.substring(0, chunkSize * maxChunks);
requiredChunks = maxChunks;
}
}
for (int i = 0; i < requiredChunks; ++i) {
int start = i * chunkSize;
String key = String("rdd") + i;
gPrefs.putString(key.c_str(), stored.substring(start, min((int)stored.length(), start + chunkSize)));
}
gPrefs.putInt("rddn", requiredChunks);
gLastRegisterDiagDetails = stored;
}
static void clearRegisterDiagDetailsFromPrefs() {
gPrefs.remove("reg_diag_details");
gPrefs.remove("rddn");
for (int i = 0; i < 12; ++i) {
String key = String("rdd") + i;
gPrefs.remove(key.c_str());
}
}
static void saveRegisterDiag(const String &status, const String &summary, const String &details) { static void saveRegisterDiag(const String &status, const String &summary, const String &details) {
gLastRegisterDiagStatus = status; gLastRegisterDiagStatus = status;
gLastRegisterDiagSummary = summary.length() > 240 ? summary.substring(0, 240) : summary; gLastRegisterDiagSummary = summary;
gLastRegisterDiagDetails = details.length() > 1800 ? details.substring(0, 1800) : details;
gLastRegisterDiagTime = String(shineNowMs()); gLastRegisterDiagTime = String(shineNowMs());
gPrefs.putString("reg_diag_status", gLastRegisterDiagStatus); gPrefs.putString("reg_diag_status", gLastRegisterDiagStatus);
gPrefs.putString("reg_diag_summary", gLastRegisterDiagSummary); gPrefs.putString("reg_diag_summary", gLastRegisterDiagSummary);
gPrefs.putString("reg_diag_details", gLastRegisterDiagDetails);
gPrefs.putString("reg_diag_time", gLastRegisterDiagTime); gPrefs.putString("reg_diag_time", gLastRegisterDiagTime);
saveRegisterDiagDetailsToPrefs(details);
} }
static void clearRegisterDiag() { static void clearRegisterDiag() {
@ -2855,8 +2927,8 @@ static void clearRegisterDiag() {
gLastRegisterDiagTime = ""; gLastRegisterDiagTime = "";
gPrefs.remove("reg_diag_status"); gPrefs.remove("reg_diag_status");
gPrefs.remove("reg_diag_summary"); gPrefs.remove("reg_diag_summary");
gPrefs.remove("reg_diag_details");
gPrefs.remove("reg_diag_time"); gPrefs.remove("reg_diag_time");
clearRegisterDiagDetailsFromPrefs();
} }
static void printRegisterDiagToSerial() { static void printRegisterDiagToSerial() {

View File

@ -1,2 +1,2 @@
client.version=1.2.169 client.version=1.2.170
server.version=1.2.158 server.version=1.2.159