Have chip-tool generate a random remote node id every time it pairs. (#8450)

This way multiple things we pair don't step on each other's toes as
far as mdns advertisements go.

Fixes https://github.com/project-chip/connectedhomeip/issues/8439
diff --git a/.github/workflows/tests.yaml b/.github/workflows/tests.yaml
index 3b4de40..9c2fb37 100644
--- a/.github/workflows/tests.yaml
+++ b/.github/workflows/tests.yaml
@@ -77,7 +77,8 @@
             - name: Build chip-tool
               timeout-minutes: 5
               run: |
-                  scripts/examples/gn_build_example.sh examples/chip-tool out/debug/standalone/ is_tsan=${USE_TSAN} config_use_separate_eventloop=${USE_SEPARATE_EVENTLOOP}
+                  # config_pair_with_random_id=false so CI runs faster.
+                  scripts/examples/gn_build_example.sh examples/chip-tool out/debug/standalone/ is_tsan=${USE_TSAN} config_use_separate_eventloop=${USE_SEPARATE_EVENTLOOP} config_pair_with_random_id=false
             - name: Copy objdir
               run: |
                   # The idea is to not upload our objdir unless builds have
@@ -162,7 +163,8 @@
             - name: Build chip-tool
               timeout-minutes: 5
               run: |
-                  scripts/examples/gn_build_example.sh examples/chip-tool out/debug/standalone/ is_tsan=${USE_TSAN} config_use_separate_eventloop=${USE_SEPARATE_EVENTLOOP}
+                  # config_pair_with_random_id=false so CI runs faster.
+                  scripts/examples/gn_build_example.sh examples/chip-tool out/debug/standalone/ is_tsan=${USE_TSAN} config_use_separate_eventloop=${USE_SEPARATE_EVENTLOOP} config_pair_with_random_id=false
             - name: Copy objdir
               run: |
                   # The idea is to not upload our objdir unless builds have
diff --git a/examples/chip-tool/BUILD.gn b/examples/chip-tool/BUILD.gn
index 26f9168..cc7f5f7 100644
--- a/examples/chip-tool/BUILD.gn
+++ b/examples/chip-tool/BUILD.gn
@@ -22,6 +22,11 @@
 declare_args() {
   # Use a separate eventloop for CHIP tasks
   config_use_separate_eventloop = true
+
+  # Generate a new node id on every pairing.  This significantly slows
+  # down running a lot of pairings (because of all the disk traffic for
+  # saving the config file), so we disable it in some configurations.
+  config_pair_with_random_id = true
 }
 
 executable("chip-tool") {
@@ -40,7 +45,10 @@
     "main.cpp",
   ]
 
-  defines = [ "CONFIG_USE_SEPARATE_EVENTLOOP=${config_use_separate_eventloop}" ]
+  defines = [
+    "CONFIG_USE_SEPARATE_EVENTLOOP=${config_use_separate_eventloop}",
+    "CONFIG_PAIR_WITH_RANDOM_ID=${config_pair_with_random_id}",
+  ]
 
   deps = [
     "${chip_root}/src/controller/data_model",
diff --git a/examples/chip-tool/commands/common/Commands.cpp b/examples/chip-tool/commands/common/Commands.cpp
index b8cca51..8623587 100644
--- a/examples/chip-tool/commands/common/Commands.cpp
+++ b/examples/chip-tool/commands/common/Commands.cpp
@@ -38,11 +38,13 @@
     }
 }
 
-int Commands::Run(NodeId localId, NodeId remoteId, int argc, char ** argv)
+int Commands::Run(int argc, char ** argv)
 {
     CHIP_ERROR err = CHIP_NO_ERROR;
     chip::Controller::CommissionerInitParams initParams;
     Command * command = nullptr;
+    NodeId localId;
+    NodeId remoteId;
 
     err = chip::Platform::MemoryInit();
     VerifyOrExit(err == CHIP_NO_ERROR, ChipLogError(Controller, "Init Memory failure: %s", chip::ErrorStr(err)));
@@ -56,6 +58,11 @@
     VerifyOrExit(err == CHIP_NO_ERROR, ChipLogError(Controller, "Init Storage failure: %s", chip::ErrorStr(err)));
 
     chip::Logging::SetLogFilter(mStorage.GetLoggingLevel());
+    localId  = mStorage.GetLocalNodeId();
+    remoteId = mStorage.GetRemoteNodeId();
+
+    ChipLogProgress(Controller, "Read local id 0x" ChipLogFormatX64 ", remote id 0x" ChipLogFormatX64, ChipLogValueX64(localId),
+                    ChipLogValueX64(remoteId));
 
     initParams.storageDelegate = &mStorage;
 
diff --git a/examples/chip-tool/commands/common/Commands.h b/examples/chip-tool/commands/common/Commands.h
index 1e6d415..56ccf10 100644
--- a/examples/chip-tool/commands/common/Commands.h
+++ b/examples/chip-tool/commands/common/Commands.h
@@ -30,7 +30,7 @@
     using CommandsVector = ::std::vector<std::unique_ptr<Command>>;
 
     void Register(const char * clusterName, commands_list commandsList);
-    int Run(NodeId localId, NodeId remoteId, int argc, char ** argv);
+    int Run(int argc, char ** argv);
 
 private:
     // *ranCommand will be set to the command we ran if we get as far as running
diff --git a/examples/chip-tool/commands/pairing/PairingCommand.cpp b/examples/chip-tool/commands/pairing/PairingCommand.cpp
index f3db0a1..bf9264c 100644
--- a/examples/chip-tool/commands/pairing/PairingCommand.cpp
+++ b/examples/chip-tool/commands/pairing/PairingCommand.cpp
@@ -18,7 +18,9 @@
 
 #include "PairingCommand.h"
 #include "platform/PlatformManager.h"
+#include <crypto/CHIPCryptoPAL.h>
 #include <lib/core/CHIPSafeCasts.h>
+#include <support/logging/CHIPLogging.h>
 
 #include <setup_payload/ManualSetupPayloadParser.h>
 #include <setup_payload/QRCodeSetupPayloadParser.h>
@@ -35,6 +37,18 @@
     GetExecContext()->commissioner->RegisterDeviceAddressUpdateDelegate(this);
     GetExecContext()->commissioner->RegisterPairingDelegate(this);
 
+#if CONFIG_PAIR_WITH_RANDOM_ID
+    // Generate a random remote id so we don't end up reusing the same node id
+    // for different nodes.
+    NodeId randomId;
+    DRBG_get_bytes(reinterpret_cast<uint8_t *>(&randomId), sizeof(randomId));
+    ChipLogProgress(Controller, "Generated random node id: 0x" ChipLogFormatX64, ChipLogValueX64(randomId));
+    if (GetExecContext()->storage->SetRemoteNodeId(randomId) == CHIP_NO_ERROR)
+    {
+        GetExecContext()->remoteId = randomId;
+    }
+#endif // CONFIG_PAIR_WITH_RANDOM_ID
+
     err = RunInternal(GetExecContext()->remoteId);
     VerifyOrExit(err == CHIP_NO_ERROR, ChipLogError(chipTool, "Init Failure! PairDevice: %s", ErrorStr(err)));
 
diff --git a/examples/chip-tool/commands/reporting/Commands.h b/examples/chip-tool/commands/reporting/Commands.h
index 56900a5..cc289ce 100644
--- a/examples/chip-tool/commands/reporting/Commands.h
+++ b/examples/chip-tool/commands/reporting/Commands.h
@@ -60,54 +60,55 @@
     void AddReportCallbacks(uint8_t endpointId) override
     {
         chip::app::CHIPDeviceCallbacksMgr & callbacksMgr = chip::app::CHIPDeviceCallbacksMgr::GetInstance();
-        callbacksMgr.AddReportCallback(chip::kTestDeviceNodeId, endpointId, 0x000F, 0x0055,
+        callbacksMgr.AddReportCallback(GetExecContext()->storage->GetRemoteNodeId(), endpointId, 0x000F, 0x0055,
                                        onReportBinaryInputBasicPresentValueCallback->Cancel());
-        callbacksMgr.AddReportCallback(chip::kTestDeviceNodeId, endpointId, 0x000F, 0x006F,
+        callbacksMgr.AddReportCallback(GetExecContext()->storage->GetRemoteNodeId(), endpointId, 0x000F, 0x006F,
                                        onReportBinaryInputBasicStatusFlagsCallback->Cancel());
-        callbacksMgr.AddReportCallback(chip::kTestDeviceNodeId, endpointId, 0x0300, 0x0000,
+        callbacksMgr.AddReportCallback(GetExecContext()->storage->GetRemoteNodeId(), endpointId, 0x0300, 0x0000,
                                        onReportColorControlCurrentHueCallback->Cancel());
-        callbacksMgr.AddReportCallback(chip::kTestDeviceNodeId, endpointId, 0x0300, 0x0001,
+        callbacksMgr.AddReportCallback(GetExecContext()->storage->GetRemoteNodeId(), endpointId, 0x0300, 0x0001,
                                        onReportColorControlCurrentSaturationCallback->Cancel());
-        callbacksMgr.AddReportCallback(chip::kTestDeviceNodeId, endpointId, 0x0300, 0x0003,
+        callbacksMgr.AddReportCallback(GetExecContext()->storage->GetRemoteNodeId(), endpointId, 0x0300, 0x0003,
                                        onReportColorControlCurrentXCallback->Cancel());
-        callbacksMgr.AddReportCallback(chip::kTestDeviceNodeId, endpointId, 0x0300, 0x0004,
+        callbacksMgr.AddReportCallback(GetExecContext()->storage->GetRemoteNodeId(), endpointId, 0x0300, 0x0004,
                                        onReportColorControlCurrentYCallback->Cancel());
-        callbacksMgr.AddReportCallback(chip::kTestDeviceNodeId, endpointId, 0x0300, 0x0007,
+        callbacksMgr.AddReportCallback(GetExecContext()->storage->GetRemoteNodeId(), endpointId, 0x0300, 0x0007,
                                        onReportColorControlColorTemperatureCallback->Cancel());
-        callbacksMgr.AddReportCallback(chip::kTestDeviceNodeId, endpointId, 0x0101, 0x0000,
+        callbacksMgr.AddReportCallback(GetExecContext()->storage->GetRemoteNodeId(), endpointId, 0x0101, 0x0000,
                                        onReportDoorLockLockStateCallback->Cancel());
-        callbacksMgr.AddReportCallback(chip::kTestDeviceNodeId, endpointId, 0x0008, 0x0000,
+        callbacksMgr.AddReportCallback(GetExecContext()->storage->GetRemoteNodeId(), endpointId, 0x0008, 0x0000,
                                        onReportLevelControlCurrentLevelCallback->Cancel());
-        callbacksMgr.AddReportCallback(chip::kTestDeviceNodeId, endpointId, 0x0406, 0x0000,
+        callbacksMgr.AddReportCallback(GetExecContext()->storage->GetRemoteNodeId(), endpointId, 0x0406, 0x0000,
                                        onReportOccupancySensingOccupancyCallback->Cancel());
-        callbacksMgr.AddReportCallback(chip::kTestDeviceNodeId, endpointId, 0x0006, 0x0000, onReportOnOffOnOffCallback->Cancel());
-        callbacksMgr.AddReportCallback(chip::kTestDeviceNodeId, endpointId, 0x0403, 0x0000,
+        callbacksMgr.AddReportCallback(GetExecContext()->storage->GetRemoteNodeId(), endpointId, 0x0006, 0x0000,
+                                       onReportOnOffOnOffCallback->Cancel());
+        callbacksMgr.AddReportCallback(GetExecContext()->storage->GetRemoteNodeId(), endpointId, 0x0403, 0x0000,
                                        onReportPressureMeasurementMeasuredValueCallback->Cancel());
-        callbacksMgr.AddReportCallback(chip::kTestDeviceNodeId, endpointId, 0x0200, 0x0013,
+        callbacksMgr.AddReportCallback(GetExecContext()->storage->GetRemoteNodeId(), endpointId, 0x0200, 0x0013,
                                        onReportPumpConfigurationAndControlCapacityCallback->Cancel());
-        callbacksMgr.AddReportCallback(chip::kTestDeviceNodeId, endpointId, 0x0405, 0x0000,
+        callbacksMgr.AddReportCallback(GetExecContext()->storage->GetRemoteNodeId(), endpointId, 0x0405, 0x0000,
                                        onReportRelativeHumidityMeasurementMeasuredValueCallback->Cancel());
-        callbacksMgr.AddReportCallback(chip::kTestDeviceNodeId, endpointId, 0x003B, 0x0001,
+        callbacksMgr.AddReportCallback(GetExecContext()->storage->GetRemoteNodeId(), endpointId, 0x003B, 0x0001,
                                        onReportSwitchCurrentPositionCallback->Cancel());
-        callbacksMgr.AddReportCallback(chip::kTestDeviceNodeId, endpointId, 0x0402, 0x0000,
+        callbacksMgr.AddReportCallback(GetExecContext()->storage->GetRemoteNodeId(), endpointId, 0x0402, 0x0000,
                                        onReportTemperatureMeasurementMeasuredValueCallback->Cancel());
-        callbacksMgr.AddReportCallback(chip::kTestDeviceNodeId, endpointId, 0x0201, 0x0000,
+        callbacksMgr.AddReportCallback(GetExecContext()->storage->GetRemoteNodeId(), endpointId, 0x0201, 0x0000,
                                        onReportThermostatLocalTemperatureCallback->Cancel());
-        callbacksMgr.AddReportCallback(chip::kTestDeviceNodeId, endpointId, 0x0102, 0x0008,
+        callbacksMgr.AddReportCallback(GetExecContext()->storage->GetRemoteNodeId(), endpointId, 0x0102, 0x0008,
                                        onReportWindowCoveringCurrentPositionLiftPercentageCallback->Cancel());
-        callbacksMgr.AddReportCallback(chip::kTestDeviceNodeId, endpointId, 0x0102, 0x0009,
+        callbacksMgr.AddReportCallback(GetExecContext()->storage->GetRemoteNodeId(), endpointId, 0x0102, 0x0009,
                                        onReportWindowCoveringCurrentPositionTiltPercentageCallback->Cancel());
-        callbacksMgr.AddReportCallback(chip::kTestDeviceNodeId, endpointId, 0x0102, 0x000A,
+        callbacksMgr.AddReportCallback(GetExecContext()->storage->GetRemoteNodeId(), endpointId, 0x0102, 0x000A,
                                        onReportWindowCoveringOperationalStatusCallback->Cancel());
-        callbacksMgr.AddReportCallback(chip::kTestDeviceNodeId, endpointId, 0x0102, 0x000B,
+        callbacksMgr.AddReportCallback(GetExecContext()->storage->GetRemoteNodeId(), endpointId, 0x0102, 0x000B,
                                        onReportWindowCoveringTargetPositionLiftPercent100thsCallback->Cancel());
-        callbacksMgr.AddReportCallback(chip::kTestDeviceNodeId, endpointId, 0x0102, 0x000C,
+        callbacksMgr.AddReportCallback(GetExecContext()->storage->GetRemoteNodeId(), endpointId, 0x0102, 0x000C,
                                        onReportWindowCoveringTargetPositionTiltPercent100thsCallback->Cancel());
-        callbacksMgr.AddReportCallback(chip::kTestDeviceNodeId, endpointId, 0x0102, 0x000E,
+        callbacksMgr.AddReportCallback(GetExecContext()->storage->GetRemoteNodeId(), endpointId, 0x0102, 0x000E,
                                        onReportWindowCoveringCurrentPositionLiftPercent100thsCallback->Cancel());
-        callbacksMgr.AddReportCallback(chip::kTestDeviceNodeId, endpointId, 0x0102, 0x000F,
+        callbacksMgr.AddReportCallback(GetExecContext()->storage->GetRemoteNodeId(), endpointId, 0x0102, 0x000F,
                                        onReportWindowCoveringCurrentPositionTiltPercent100thsCallback->Cancel());
-        callbacksMgr.AddReportCallback(chip::kTestDeviceNodeId, endpointId, 0x0102, 0x001A,
+        callbacksMgr.AddReportCallback(GetExecContext()->storage->GetRemoteNodeId(), endpointId, 0x0102, 0x001A,
                                        onReportWindowCoveringSafetyStatusCallback->Cancel());
     }
 
diff --git a/examples/chip-tool/config/PersistentStorage.cpp b/examples/chip-tool/config/PersistentStorage.cpp
index 360f686..26194e3 100644
--- a/examples/chip-tool/config/PersistentStorage.cpp
+++ b/examples/chip-tool/config/PersistentStorage.cpp
@@ -17,6 +17,8 @@
  */
 #include "PersistentStorage.h"
 
+#include <lib/core/CHIPEncoding.h>
+#include <protocols/secure_channel/PASESession.h>
 #include <support/Base64.h>
 
 #include <fstream>
@@ -34,6 +36,8 @@
 constexpr const char kDefaultSectionName[] = "Default";
 constexpr const char kPortKey[]            = "ListenPort";
 constexpr const char kLoggingKey[]         = "LoggingLevel";
+constexpr const char kLocalNodeIdKey[]     = "LocalNodeId";
+constexpr const char kRemoteNodeIdKey[]    = "RemoteNodeId";
 constexpr LogCategory kDefaultLoggingLevel = kLogCategory_Detail;
 
 namespace {
@@ -204,3 +208,44 @@
 
     return chipLogLevel;
 }
+
+NodeId PersistentStorage::GetNodeId(const char * key, NodeId defaultVal)
+{
+    CHIP_ERROR err = CHIP_NO_ERROR;
+
+    uint64_t nodeId;
+    uint16_t size = static_cast<uint16_t>(sizeof(nodeId));
+    err           = SyncGetKeyValue(key, &nodeId, size);
+    if (err == CHIP_NO_ERROR)
+    {
+        return static_cast<NodeId>(Encoding::LittleEndian::HostSwap64(nodeId));
+    }
+
+    return defaultVal;
+}
+
+NodeId PersistentStorage::GetLocalNodeId()
+{
+    return GetNodeId(kLocalNodeIdKey, kTestControllerNodeId);
+}
+
+NodeId PersistentStorage::GetRemoteNodeId()
+{
+    return GetNodeId(kRemoteNodeIdKey, kTestDeviceNodeId);
+}
+
+CHIP_ERROR PersistentStorage::SetNodeId(const char * key, NodeId value)
+{
+    uint64_t nodeId = Encoding::LittleEndian::HostSwap64(value);
+    return SyncSetKeyValue(key, &nodeId, sizeof(nodeId));
+}
+
+CHIP_ERROR PersistentStorage::SetLocalNodeId(NodeId nodeId)
+{
+    return SetNodeId(kLocalNodeIdKey, nodeId);
+}
+
+CHIP_ERROR PersistentStorage::SetRemoteNodeId(NodeId nodeId)
+{
+    return SetNodeId(kRemoteNodeIdKey, nodeId);
+}
diff --git a/examples/chip-tool/config/PersistentStorage.h b/examples/chip-tool/config/PersistentStorage.h
index a8d9913..6f275ef 100644
--- a/examples/chip-tool/config/PersistentStorage.h
+++ b/examples/chip-tool/config/PersistentStorage.h
@@ -18,6 +18,7 @@
 
 #pragma once
 
+#include <app/util/basic-types.h>
 #include <controller/CHIPDeviceController.h>
 #include <inipp/inipp.h>
 #include <support/logging/CHIPLogging.h>
@@ -35,7 +36,19 @@
     uint16_t GetListenPort();
     chip::Logging::LogCategory GetLoggingLevel();
 
+    // Return the stored node ids, or the default ones if nothing is stored.
+    chip::NodeId GetLocalNodeId();
+    chip::NodeId GetRemoteNodeId();
+
+    // Store node ids.
+    CHIP_ERROR SetLocalNodeId(chip::NodeId nodeId);
+    CHIP_ERROR SetRemoteNodeId(chip::NodeId nodeId);
+
 private:
+    // Helpers for node ids.
+    chip::NodeId GetNodeId(const char * key, chip::NodeId defaultVal);
+    CHIP_ERROR SetNodeId(const char * key, chip::NodeId value);
+
     CHIP_ERROR CommitConfig();
     inipp::Ini<char> mConfig;
 };
diff --git a/examples/chip-tool/main.cpp b/examples/chip-tool/main.cpp
index 08b5923..c92fbd1 100644
--- a/examples/chip-tool/main.cpp
+++ b/examples/chip-tool/main.cpp
@@ -25,8 +25,6 @@
 #include "commands/reporting/Commands.h"
 #include "commands/tests/Commands.h"
 
-#include <protocols/secure_channel/PASESession.h>
-
 // ================================================================================
 // Main Code
 // ================================================================================
@@ -40,5 +38,5 @@
     registerCommandsTests(commands);
     registerClusters(commands);
 
-    return commands.Run(chip::kTestControllerNodeId, chip::kTestDeviceNodeId, argc, argv);
+    return commands.Run(argc, argv);
 }
diff --git a/examples/chip-tool/templates/reporting-commands.zapt b/examples/chip-tool/templates/reporting-commands.zapt
index 0c827b2..db072fc 100644
--- a/examples/chip-tool/templates/reporting-commands.zapt
+++ b/examples/chip-tool/templates/reporting-commands.zapt
@@ -31,7 +31,7 @@
 {{#chip_clusters}}
 {{#chip_server_cluster_attributes}}
 {{#if isReportableAttribute}}
-        callbacksMgr.AddReportCallback(chip::kTestDeviceNodeId, endpointId, {{asHex parent.code 4}}, {{asHex code 4}}, onReport{{asCamelCased parent.name false}}{{asCamelCased name false}}Callback->Cancel());
+        callbacksMgr.AddReportCallback(GetExecContext()->storage->GetRemoteNodeId(), endpointId, {{asHex parent.code 4}}, {{asHex code 4}}, onReport{{asCamelCased parent.name false}}{{asCamelCased name false}}Callback->Cancel());
 {{/if}}
 {{/chip_server_cluster_attributes}}
 {{/chip_clusters}}