ESP32: сохранять полный текст ошибки регистрации
This commit is contained in:
parent
436e1f0c53
commit
04252e006b
@ -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.
|
||||||
|
|
||||||
@ -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() {
|
||||||
|
|||||||
@ -1,2 +1,2 @@
|
|||||||
client.version=1.2.169
|
client.version=1.2.170
|
||||||
server.version=1.2.158
|
server.version=1.2.159
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user