Add smsgbroadcast RPC command for messaging all known peers
New command: smsgbroadcast <addrFrom> <message> Iterates all public keys in smsgDB and sends an encrypted message to each. Skips the sender's own address. Reports sent/failed counts. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -47,7 +47,7 @@ public:
|
||||
void refreshMessageTable()
|
||||
{
|
||||
cachedMessageTable.clear();
|
||||
|
||||
|
||||
if (parent->getWalletModel()->getEncryptionStatus() == WalletModel::Locked)
|
||||
{
|
||||
// -- messages are stored encrypted, can't load them without the private keys
|
||||
@@ -84,7 +84,7 @@ public:
|
||||
|
||||
sent_datetime .setTime_t(msg.timestamp);
|
||||
received_datetime.setTime_t(smsgStored.timeReceived);
|
||||
|
||||
|
||||
memcpy(&vchKey[0], chKey, 18);
|
||||
|
||||
addMessageEntry(MessageTableEntry(vchKey,
|
||||
@@ -112,7 +112,7 @@ public:
|
||||
|
||||
sent_datetime .setTime_t(msg.timestamp);
|
||||
received_datetime.setTime_t(smsgStored.timeReceived);
|
||||
|
||||
|
||||
memcpy(&vchKey[0], chKey, 18);
|
||||
|
||||
addMessageEntry(MessageTableEntry(vchKey,
|
||||
@@ -124,10 +124,16 @@ public:
|
||||
received_datetime,
|
||||
(char*)&msg.vchMessage[0]),
|
||||
true);
|
||||
} else
|
||||
{
|
||||
printf("refreshMessageTable: outbox decrypt failed (err %d) for addr %s\n", decryptResult, smsgStored.sAddrOutbox.c_str());
|
||||
}
|
||||
};
|
||||
|
||||
delete it;
|
||||
|
||||
printf("refreshMessageTable: inbox %u found, %u decrypted; outbox %u found, %u decrypted\n",
|
||||
nInbox, nInboxDecrypted, nOutbox, nOutboxDecrypted);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+90
-1
@@ -889,7 +889,96 @@ Value smsgbuckets(const Array& params, bool fHelp)
|
||||
result.push_back(Pair("result", "Unknown Mode."));
|
||||
result.push_back(Pair("expected", "[stats|dump]."));
|
||||
};
|
||||
|
||||
|
||||
|
||||
return result;
|
||||
};
|
||||
|
||||
Value smsgbroadcast(const Array& params, bool fHelp)
|
||||
{
|
||||
if (fHelp || params.size() != 2)
|
||||
throw runtime_error(
|
||||
"smsgbroadcast <addrFrom> <message>\n"
|
||||
"Send an encrypted message to all known public keys in the smsgDB.\n"
|
||||
"Returns the number of recipients and any failures.");
|
||||
|
||||
if (!fSecMsgEnabled)
|
||||
throw runtime_error("Secure messaging is disabled.");
|
||||
|
||||
if (pwalletMain->IsLocked())
|
||||
throw runtime_error("Wallet is locked.");
|
||||
|
||||
std::string addrFrom = params[0].get_str();
|
||||
std::string msg = params[1].get_str();
|
||||
|
||||
// Validate sender address
|
||||
CTrianglesAddress coinAddrFrom(addrFrom);
|
||||
if (!coinAddrFrom.IsValid())
|
||||
throw runtime_error("Invalid from address.");
|
||||
|
||||
Object result;
|
||||
uint32_t nSent = 0;
|
||||
uint32_t nFailed = 0;
|
||||
Array failures;
|
||||
|
||||
{
|
||||
LOCK(cs_smsgDB);
|
||||
|
||||
SecMsgDB dbPub;
|
||||
if (!dbPub.Open("r"))
|
||||
throw runtime_error("Could not open smsgDB.");
|
||||
|
||||
// Iterate all "pk" entries
|
||||
std::string sPrefix("pk");
|
||||
leveldb::Iterator* it = dbPub.pdb->NewIterator(leveldb::ReadOptions());
|
||||
for (it->Seek(sPrefix); it->Valid(); it->Next())
|
||||
{
|
||||
std::string key = it->key().ToString();
|
||||
if (key.size() < 2 || key[0] != 'p' || key[1] != 'k')
|
||||
break;
|
||||
|
||||
// Deserialize the CKeyID from the key (after "pk" prefix)
|
||||
CDataStream ssKey(key.data(), key.data() + key.size(), SER_DISK, CLIENT_VERSION);
|
||||
char prefix[2];
|
||||
ssKey >> prefix[0];
|
||||
ssKey >> prefix[1];
|
||||
CKeyID ckidTo;
|
||||
ssKey >> ckidTo;
|
||||
|
||||
// Convert CKeyID to address string
|
||||
CTrianglesAddress addrTo(ckidTo);
|
||||
if (!addrTo.IsValid())
|
||||
continue;
|
||||
|
||||
std::string sAddrTo = addrTo.ToString();
|
||||
|
||||
// Skip sending to self
|
||||
if (sAddrTo == addrFrom)
|
||||
continue;
|
||||
|
||||
std::string sError;
|
||||
if (SecureMsgSend(addrFrom, sAddrTo, msg, sError) != 0)
|
||||
{
|
||||
nFailed++;
|
||||
Object objFail;
|
||||
objFail.push_back(Pair("address", sAddrTo));
|
||||
objFail.push_back(Pair("error", sError));
|
||||
failures.push_back(objFail);
|
||||
} else
|
||||
{
|
||||
nSent++;
|
||||
}
|
||||
}
|
||||
delete it;
|
||||
}
|
||||
|
||||
char cbuf[256];
|
||||
snprintf(cbuf, sizeof(cbuf), "Broadcast sent to %u recipients, %u failed.", nSent, nFailed);
|
||||
result.push_back(Pair("result", std::string(cbuf)));
|
||||
result.push_back(Pair("sent", (int)nSent));
|
||||
result.push_back(Pair("failed", (int)nFailed));
|
||||
if (nFailed > 0)
|
||||
result.push_back(Pair("failures", failures));
|
||||
|
||||
return result;
|
||||
};
|
||||
|
||||
@@ -336,6 +336,7 @@ static const CRPCCommand vRPCCommands[] =
|
||||
{ "smsginbox", &smsginbox, false, false},
|
||||
{ "smsgoutbox", &smsgoutbox, false, false},
|
||||
{ "smsgbuckets", &smsgbuckets, false, false},
|
||||
{ "smsgbroadcast", &smsgbroadcast, false, false},
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -247,6 +247,7 @@ extern json_spirit::Value smsgsendanon(const json_spirit::Array& params, bool fH
|
||||
extern json_spirit::Value smsginbox(const json_spirit::Array& params, bool fHelp);
|
||||
extern json_spirit::Value smsgoutbox(const json_spirit::Array& params, bool fHelp);
|
||||
extern json_spirit::Value smsgbuckets(const json_spirit::Array& params, bool fHelp);
|
||||
extern json_spirit::Value smsgbroadcast(const json_spirit::Array& params, bool fHelp);
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
Reference in New Issue
Block a user