Skip to content

Commit 2acc8c1

Browse files
committed
fix: restore light node rewards and persist pending rewards across restarts
- Fix light node reward processing in process_reward_window_internal (Path 1): merge reward_light_nodes into all_summaries alongside reward_heartbeats, matching the existing correct behavior in the receiver/sync path (Path 4) - Fix light node reward processing in MacroBlock creator path (Path 3): same merge of reward_light_nodes, ensuring the creator node calculates identical rewards to all receiver nodes (full determinism across all paths) - Add RocksDB persistence for pending rewards in Path 3 (creator) and Path 4 (receiver/sync): save_pending_reward called after every emission MacroBlock so rewards survive node restarts - Add startup recovery from state snapshot: if RocksDB pending_rewards is empty (pre-v3.35 nodes that never persisted), recover baseline amounts from state snapshot accounts and immediately seed RocksDB for future restarts - Fix missing next_ping_time and next_ping_window in already_registered response for light nodes (both state check and gossip registry check), preventing undefined ping timer after wallet restore on mobile - Fix duplicate node registration for Super nodes in handle_register_node: check storage.get_nodes_by_wallet upfront and return already_registered response instead of creating a new registration TX - Fix clock drift handling in HealthPing: decouple signature verification from message age check so last_block_height is always updated on valid sig - Drop consensus messages during fast sync when local node is far behind network height to prevent invalid block reports Made-with: Cursor
1 parent 3dfd4c7 commit 2acc8c1

5 files changed

Lines changed: 300 additions & 113 deletions

File tree

applications/qnet-mobile/src/components/WalletManager.js

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5883,14 +5883,19 @@ export class WalletManager {
58835883
await AsyncStorage.setItem(`node_next_ping_${activationCode}`, registrationResult.next_ping_time.toString());
58845884
}
58855885

5886+
const alreadyRegistered = !!(registrationResult && registrationResult.already_registered);
5887+
58865888
return {
58875889
success: true,
5890+
alreadyRegistered,
58885891
nodeType,
58895892
pseudonym: (registrationResult && registrationResult.node_id) || systemPseudonym,
58905893
burnTxHash: burnTxHash || null,
5891-
message: registrationResult
5892-
? 'Node successfully activated and registered in blockchain'
5893-
: 'Node activation saved locally. Network registration will retry automatically.',
5894+
message: alreadyRegistered
5895+
? (registrationResult.message || 'Node already registered. Your existing node has been restored.')
5896+
: registrationResult
5897+
? 'Node successfully activated and registered in blockchain'
5898+
: 'Node activation saved locally. Network registration will retry automatically.',
58945899
nextPingTime: registrationResult ? registrationResult.next_ping_time : null,
58955900
nextPingWindow: registrationResult ? registrationResult.next_ping_window : null,
58965901
quantumSecured,

applications/qnet-mobile/src/screens/WalletScreen.js

Lines changed: 23 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1768,19 +1768,29 @@ const WalletScreen = () => {
17681768
burnTxHash: result.burnTxHash || 'registered',
17691769
walletAddress: wallet.qnetAddress || wallet.address
17701770
}));
1771-
1772-
// Start automatic ping interval (every 4 hours)
1773-
// No automatic ping interval
1774-
1775-
showAlert(
1776-
'Node Activated!',
1777-
`Your ${result.nodeType || 'light'} node has been successfully activated and registered in the network.\n\nNode ID: ${activationInputCode.trim()}\nSystem ID: ${result.pseudonym}`,
1778-
[{ text: 'OK', onPress: () => {
1779-
setShowActivationInput(false);
1780-
setActivationInputCode('');
1781-
loadNodeRewards();
1782-
}}]
1783-
);
1771+
1772+
if (result.alreadyRegistered) {
1773+
// Node was already on-chain — just restore it locally, no new TX
1774+
showAlert(
1775+
'Node Restored!',
1776+
`Your existing ${nodeType} node has been successfully restored.\n\nNode ID: ${activationInputCode.trim()}\nSystem ID: ${result.pseudonym}`,
1777+
[{ text: 'OK', onPress: () => {
1778+
setShowActivationInput(false);
1779+
setActivationInputCode('');
1780+
loadNodeRewards();
1781+
}}]
1782+
);
1783+
} else {
1784+
showAlert(
1785+
'Node Activated!',
1786+
`Your ${nodeType} node has been successfully activated and registered in the network.\n\nNode ID: ${activationInputCode.trim()}\nSystem ID: ${result.pseudonym}`,
1787+
[{ text: 'OK', onPress: () => {
1788+
setShowActivationInput(false);
1789+
setActivationInputCode('');
1790+
loadNodeRewards();
1791+
}}]
1792+
);
1793+
}
17841794
} else {
17851795
throw new Error(result.error || 'Failed to activate node');
17861796
}

0 commit comments

Comments
 (0)