Compare commits

...

2 Commits

2 changed files with 90 additions and 38 deletions

View File

@ -8,9 +8,6 @@
#include <Arduino_GFX_Library.h>
#include <TouchDrvCSTXXX.hpp>
#include <mbedtls/sha256.h>
extern "C" int ge25519_is_canonical(const unsigned char *s);
extern "C" int ge25519_is_on_curve(const unsigned char *p);
#include <mbedtls/base64.h>
#include <Ed25519.h>
#include <sodium.h>
@ -38,6 +35,17 @@ extern "C" int ge25519_is_on_curve(const unsigned char *p);
#define TAP_CANCEL_THRESHOLD 18
#define MAX_SCAN_RESULTS 8
#define MAX_SAVED_WIFI_NETWORKS 8
extern "C" {
typedef int32_t fe25519[10];
typedef struct {
fe25519 X;
fe25519 Y;
fe25519 Z;
fe25519 T;
} ge25519_p3;
int ge25519_frombytes(ge25519_p3 *h, const unsigned char *s);
}
#define WIFI_CONNECT_TIMEOUT_MS 12000
#define WIFI_RECONNECT_FAST_MS 10000
#define WIFI_RECONNECT_SLOW_MS 30000
@ -263,6 +271,11 @@ static String gLastRegisterDiagStatus = "none";
static String gLastRegisterDiagSummary;
static String gLastRegisterDiagDetails;
static String gLastRegisterDiagTime;
static String gRegisterTriggerSource = "manual";
static unsigned long gBootMillis = 0;
static bool gAutoRegisterTestArmed = true;
static bool gAutoRegisterTestStarted = false;
static bool gAutoRegisterTestFinished = false;
static String gSerialCommandBuffer;
static String gShineSessionId;
static String gShineSessionKey;
@ -415,6 +428,7 @@ 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 bool awaitTransactionConfirmation(const String &signatureB58, String &messageOut);
static bool registerHomeserverOnSolana(String &messageOut);
static void executeRegisterAccountFlow(const char *triggerSource, bool showResultScreen);
static void loadRegisterDiagDetailsFromPrefs();
static void saveRegisterDiagDetailsToPrefs(const String &details);
static void clearRegisterDiagDetailsFromPrefs();
@ -660,6 +674,18 @@ static String bytesToBase64String(const uint8_t *data, size_t len) {
return base64Std(data, len);
}
static String bytesToHexString(const uint8_t *data, size_t len) {
static const char *kHex = "0123456789abcdef";
String out;
out.reserve(len * 2);
for (size_t i = 0; i < len; ++i) {
uint8_t v = data[i];
out += kHex[(v >> 4) & 0x0F];
out += kHex[v & 0x0F];
}
return out;
}
static String normalizeLoginValue(const String &value) {
String out = value;
out.trim();
@ -918,9 +944,8 @@ static bool findProgramAddress(const std::vector<std::vector<uint8_t>> &seeds, c
reinterpret_cast<const unsigned char *>(kProgramDerivedAddressMarker),
strlen(kProgramDerivedAddressMarker));
crypto_hash_sha256_final(&st, out32);
bool isCanonical = ge25519_is_canonical(out32) != 0;
bool isOnCurve = ge25519_is_on_curve(out32) != 0;
if (!(isCanonical && isOnCurve)) {
ge25519_p3 point;
if (ge25519_frombytes(&point, out32) != 0) {
return true;
}
}
@ -1205,7 +1230,7 @@ static std::vector<uint8_t> buildUnsignedCreateRecord(
out.push_back(kBlockTypeServerProfile);
out.push_back(0);
out.push_back(1);
out.push_back(1);
out.push_back(0);
out.push_back(0);
pushStrU8(out, serverAddress);
out.push_back(0);
@ -1518,11 +1543,11 @@ static std::vector<uint8_t> buildLegacyMessage(
accountKeys.emplace_back(userPda, userPda + 32);
accountKeys.emplace_back(inflowVault, inflowVault + 32);
accountKeys.emplace_back(systemProgram, systemProgram + 32);
accountKeys.emplace_back(sysvarInstructions, sysvarInstructions + 32);
accountKeys.emplace_back(economyConfig, economyConfig + 32);
accountKeys.emplace_back(loginGuardProgram, loginGuardProgram + 32);
accountKeys.emplace_back(economyConfig, economyConfig + 32);
accountKeys.emplace_back(ed25519Program, ed25519Program + 32);
accountKeys.emplace_back(usersProgram, usersProgram + 32);
accountKeys.emplace_back(sysvarInstructions, sysvarInstructions + 32);
std::vector<uint8_t> msg;
msg.reserve(512);
@ -1536,25 +1561,25 @@ static std::vector<uint8_t> buildLegacyMessage(
msg.insert(msg.end(), recentBlockhash, recentBlockhash + 32);
shortVecEncode(3, msg);
msg.push_back(7);
msg.push_back(6);
msg.push_back(0);
shortVecEncode(edRootData.size(), msg);
msg.insert(msg.end(), edRootData.begin(), edRootData.end());
msg.push_back(7);
msg.push_back(6);
msg.push_back(0);
shortVecEncode(edBchData.size(), msg);
msg.insert(msg.end(), edBchData.begin(), edBchData.end());
msg.push_back(8);
msg.push_back(7);
msg.push_back(7);
msg.push_back(0);
msg.push_back(1);
msg.push_back(3);
msg.push_back(2);
msg.push_back(4);
msg.push_back(8);
msg.push_back(5);
msg.push_back(6);
msg.push_back(4);
shortVecEncode(createData.size(), msg);
msg.insert(msg.end(), createData.begin(), createData.end());
return msg;
@ -1606,6 +1631,9 @@ static bool registerHomeserverOnSolana(String &messageOut) {
};
String cleanLogin = normalizeLoginValue(gLoginValue);
diagDetails += String("trigger=") + gRegisterTriggerSource + "\n";
diagDetails += String("boot_millis=") + String(gBootMillis) + "\n";
diagDetails += String("test_uptime_ms=") + String(millis()) + "\n";
diagDetails += String("login=") + cleanLogin + "\n";
diagDetails += String("rpc=") + gSolanaRpcUrl + "\n";
diagDetails += String("shine_server=") + gShineServerUrl + "\n";
@ -1717,6 +1745,7 @@ static bool registerHomeserverOnSolana(String &messageOut) {
diagDetails += String("device_pub=") + bytesToBase58(devicePub, 32) + "\n";
String blockchainName = cleanLogin + "-001";
diagDetails += String("blockchain_name=") + blockchainName + "\n";
std::vector<uint8_t> lastBlockState = buildLastBlockStateBytes(cleanLogin, blockchainName);
uint8_t lastBlockHash[32];
uint8_t lastBlockSignature[64];
@ -1724,8 +1753,11 @@ static bool registerHomeserverOnSolana(String &messageOut) {
if (!signMessageEd25519(std::vector<uint8_t>(lastBlockHash, lastBlockHash + 32), blockchainSec, lastBlockSignature)) {
return failWithDiag("Failed to sign LastBlockState");
}
diagDetails += String("last_block_hash=") + bytesToHexString(lastBlockHash, 32) + "\n";
diagDetails += String("last_block_signature_b64=") + bytesToBase64String(lastBlockSignature, 64) + "\n";
uint64_t createdAtMs = shineNowMs();
diagDetails += String("created_at_ms=") + String((unsigned long long)createdAtMs) + "\n";
std::vector<uint8_t> unsignedRecord = buildUnsignedCreateRecord(
cleanLogin, blockchainName, gShineServerUrl,
rootPub, devicePub, blockchainPub,
@ -1736,6 +1768,9 @@ static bool registerHomeserverOnSolana(String &messageOut) {
if (!signMessageEd25519(std::vector<uint8_t>(unsignedHash, unsignedHash + 32), rootSec, rootSignature)) {
return failWithDiag("Failed to sign PDA record");
}
diagDetails += String("unsigned_record_len=") + String((unsigned long)unsignedRecord.size()) + "\n";
diagDetails += String("unsigned_record_hash=") + bytesToHexString(unsignedHash, 32) + "\n";
diagDetails += String("root_signature_b64=") + bytesToBase64String(rootSignature, 64) + "\n";
std::vector<uint8_t> createData = buildCreateInstructionData(
cleanLogin, blockchainName, gShineServerUrl,
@ -1817,6 +1852,31 @@ static bool registerHomeserverOnSolana(String &messageOut) {
return true;
}
static void executeRegisterAccountFlow(const char *triggerSource, bool showResultScreen) {
gRegisterTriggerSource = triggerSource ? String(triggerSource) : String("manual");
prepareRegisterAccountScreen();
String registerMessage;
if (registerHomeserverOnSolana(registerMessage)) {
gRegisterResultSuccess = true;
gRegisterResultMessage = registerMessage;
gRegisterResultDetails = String("user_pda and tx signature were saved");
gAccountStatusMessage = "Registration completed";
} else {
gRegisterResultSuccess = false;
gRegisterResultMessage = registerMessage;
gRegisterResultDetails = "";
gAccountStatusMessage = registerMessage;
}
gRegisterConfirmMessage = "";
gRegisterConfirmBalanceLine = "";
gRegisterConfirmPdaLine = "";
gRegisterConfirmHomeserverLine = "";
gRegisterConfirmCanSubmit = false;
if (showResultScreen) {
showScreen(SCREEN_REGISTER_ACCOUNT_RESULT);
}
}
static void prepareRegisterAccountScreen() {
gRegisterResultMessage = "";
gRegisterResultDetails = "";
@ -2877,7 +2937,7 @@ static void loadRegisterDiagDetailsFromPrefs() {
static void saveRegisterDiagDetailsToPrefs(const String &details) {
const int chunkSize = 1400;
const int maxChunks = 12;
const int maxChunks = 20;
gPrefs.remove("reg_diag_details");
for (int i = 0; i < maxChunks; ++i) {
String key = String("rdd") + i;
@ -2909,7 +2969,7 @@ static void saveRegisterDiagDetailsToPrefs(const String &details) {
static void clearRegisterDiagDetailsFromPrefs() {
gPrefs.remove("reg_diag_details");
gPrefs.remove("rddn");
for (int i = 0; i < 12; ++i) {
for (int i = 0; i < 20; ++i) {
String key = String("rdd") + i;
gPrefs.remove(key.c_str());
}
@ -3471,27 +3531,9 @@ static void actionButtonCb(lv_event_t *event) {
prepareRegisterAccountScreen();
showScreen(SCREEN_REGISTER_ACCOUNT_CONFIRM);
break;
case ACTION_REGISTER_ACCOUNT_EXECUTE: {
String registerMessage;
if (registerHomeserverOnSolana(registerMessage)) {
gRegisterResultSuccess = true;
gRegisterResultMessage = registerMessage;
gRegisterResultDetails = String("user_pda and tx signature were saved");
gAccountStatusMessage = "Registration completed";
} else {
gRegisterResultSuccess = false;
gRegisterResultMessage = registerMessage;
gRegisterResultDetails = "";
gAccountStatusMessage = registerMessage;
}
gRegisterConfirmMessage = "";
gRegisterConfirmBalanceLine = "";
gRegisterConfirmPdaLine = "";
gRegisterConfirmHomeserverLine = "";
gRegisterConfirmCanSubmit = false;
showScreen(SCREEN_REGISTER_ACCOUNT_RESULT);
case ACTION_REGISTER_ACCOUNT_EXECUTE:
executeRegisterAccountFlow("manual", true);
break;
}
case ACTION_OPEN_WIFI:
gWifiViewMode = WIFI_VIEW_OVERVIEW;
showScreen(SCREEN_WIFI);
@ -4369,6 +4411,7 @@ static void handleSwipe(SwipeDirection swipe) {
void setup() {
Serial.begin(115200);
sodium_init();
gBootMillis = millis();
Wire.begin(PIN_I2C_SDA, PIN_I2C_SCL);
initPowerManagement();
@ -4430,6 +4473,15 @@ void loop() {
manageAccountPdaRefresh();
manageShineConnection();
if (gAutoRegisterTestArmed && !gAutoRegisterTestStarted && millis() - gBootMillis >= 15000UL) {
gAutoRegisterTestStarted = true;
gAutoRegisterTestArmed = false;
Serial.println("AUTO_REGISTER_TEST_BEGIN");
executeRegisterAccountFlow("auto-boot-15s", false);
gAutoRegisterTestFinished = true;
Serial.println("AUTO_REGISTER_TEST_END");
}
static unsigned long lastHomeRefreshMs = 0;
if (gCurrentScreen == SCREEN_HOME && !gTouchDown && millis() - lastHomeRefreshMs >= HOME_REFRESH_MS) {
lastHomeRefreshMs = millis();

View File

@ -1,2 +1,2 @@
client.version=1.2.171
server.version=1.2.160
client.version=1.2.175
server.version=1.2.164