Skip to content

Commit e6137dd

Browse files
committed
[BDAP] Add ability to just keep last message instead of all
1 parent 305ec3a commit e6137dd

File tree

4 files changed

+88
-27
lines changed

4 files changed

+88
-27
lines changed

src/bdap/rpclinking.cpp

Lines changed: 24 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -952,16 +952,17 @@ static UniValue DeniedLinkList(const JSONRPCRequest& request)
952952

953953
static UniValue SendMessage(const JSONRPCRequest& request)
954954
{
955-
if (request.fHelp || request.params.size() != 5)
955+
if (request.fHelp || request.params.size() < 5 || request.params.size() > 6)
956956
throw std::runtime_error(
957-
"link sendmessage \"account\" \"recipient\" \"type\" \"message\"\n"
957+
"link sendmessage \"account\" \"recipient\" \"type\" \"message\" \"keep_last\"\n"
958958
"Sends a realtime message from the account to the recipient. A link must be established before sending a secure message."
959959
+ HelpRequiringPassphrase() +
960960
"\nLink Send Message Arguments:\n"
961961
"1. account (string) Your BDAP sending account\n"
962962
"2. recipient (string) Your link's recipient BDAP account\n"
963963
"3. type (string) Message type\n"
964964
"4. message (string) String message value\n"
965+
"5. keep_last (bool, optional) Only store the last message for this type. Default is false.\n"
965966
"\nResult:\n"
966967
"{(json objects)\n"
967968
" \"Requestor FQDN\" (string) Requestor's BDAP full path\n"
@@ -995,6 +996,11 @@ static UniValue SendMessage(const JSONRPCRequest& request)
995996
std::vector<unsigned char> vchMessageType = vchFromValue(request.params[3]);
996997
std::vector<unsigned char> vchMessage = vchFromValue(request.params[4]);
997998

999+
bool fKeepLast = false;
1000+
if (request.params.size() > 5 && request.params[5].get_str() == "1") {
1001+
fKeepLast = true;
1002+
}
1003+
9981004
UniValue oLink(UniValue::VOBJ);
9991005
// get third shared key, derive subjectID and messageID.
10001006
CKeyEd25519 key;
@@ -1018,7 +1024,7 @@ static UniValue SendMessage(const JSONRPCRequest& request)
10181024
std::vector<unsigned char> vchWalletPubKey(newPubKey.begin(), newPubKey.end());
10191025

10201026
CUnsignedVGPMessage unsignedMessage(subjectID, messageID, vchWalletPubKey, timestamp, stoptime);
1021-
if (!unsignedMessage.EncryptMessage(vchMessageType, vchMessage, vchFromString(strSenderFQDN), vvchPubKeys, strErrorMessage))
1027+
if (!unsignedMessage.EncryptMessage(vchMessageType, vchMessage, vchFromString(strSenderFQDN), vvchPubKeys, fKeepLast, strErrorMessage))
10221028
{
10231029
throw std::runtime_error(strprintf("%s -- EncryptMessage failed: %s\n", __func__, strErrorMessage));
10241030
}
@@ -1038,6 +1044,7 @@ static UniValue SendMessage(const JSONRPCRequest& request)
10381044
oLink.push_back(Pair("message_id", unsignedMessage.MessageID.ToString()));
10391045
oLink.push_back(Pair("message_hash", vpgMessage.GetHash().ToString()));
10401046
oLink.push_back(Pair("message_size", (int)vpgMessage.vchMsg.size()));
1047+
10411048
vpgMessage.Sign(walletKey);
10421049
oLink.push_back(Pair("signature_size", (int)vpgMessage.vchSig.size()));
10431050
if (vpgMessage.CheckSignature(vchWalletPubKey)) {
@@ -1048,6 +1055,7 @@ static UniValue SendMessage(const JSONRPCRequest& request)
10481055
oLink.push_back(Pair("check_signature", "invalid"));
10491056
oLink.push_back(Pair("error_message", "failed to relay message"));
10501057
}
1058+
oLink.push_back(Pair("keep_last", fKeepLast ? "True" : "False"));
10511059
return oLink;
10521060
}
10531061

@@ -1109,18 +1117,18 @@ static UniValue GetAccountMessages(const JSONRPCRequest& request)
11091117
if (vMessages.size() > 0)
11101118
{
11111119
size_t nCounter = 1;
1112-
for (CVGPMessage& message : vMessages)
1120+
for (CVGPMessage& messageWrapper : vMessages)
11131121
{
11141122
UniValue oMessage(UniValue::VOBJ);
1115-
CUnsignedVGPMessage unsignedMessage(message.vchMsg);
1123+
CUnsignedVGPMessage unsignedMessage(messageWrapper.vchMsg);
11161124
oMessage.push_back(Pair("sender_fqdn", stringFromVch(unsignedMessage.SenderFQDN())));
11171125
oMessage.push_back(Pair("type", stringFromVch(unsignedMessage.Type())));
11181126
oMessage.push_back(Pair("message", stringFromVch(unsignedMessage.Value())));
11191127
oMessage.push_back(Pair("message_id", unsignedMessage.MessageID.ToString()));
1120-
oMessage.push_back(Pair("message_size", (int)unsignedMessage.Value().size()));
1128+
oMessage.push_back(Pair("message_size", (int)messageWrapper.vchMsg.size()));
11211129
oMessage.push_back(Pair("timestamp_epoch", unsignedMessage.nTimeStamp));
11221130
oMessage.push_back(Pair("record_num", (int)nCounter));
1123-
oMessages.push_back(Pair(message.GetHash().ToString(), oMessage));
1131+
oMessages.push_back(Pair(messageWrapper.GetHash().ToString(), oMessage));
11241132
nCounter++;
11251133
}
11261134
}
@@ -1161,25 +1169,29 @@ static UniValue GetMessages(const JSONRPCRequest& request)
11611169
if (request.params.size() > 2)
11621170
vchMessageType = vchFromValue(request.params[2]);
11631171

1172+
bool fKeepLast = false;
11641173
std::vector<CVGPMessage> vMessages;
1165-
GetMyLinkMessagesByType(vchMessageType, vchRecipientFQDN, vMessages);
1174+
GetMyLinkMessagesByType(vchMessageType, vchRecipientFQDN, vMessages, fKeepLast);
11661175
std::sort(vMessages.begin(), vMessages.end()); //sort entries by TimeStamp
1176+
if (fKeepLast)
1177+
KeepLastBySender(vMessages);
1178+
11671179
UniValue oMessages(UniValue::VOBJ);
11681180
if (vMessages.size() > 0)
11691181
{
11701182
size_t nCounter = 1;
1171-
for (CVGPMessage& message : vMessages)
1183+
for (CVGPMessage& messageWrapper : vMessages)
11721184
{
11731185
UniValue oMessage(UniValue::VOBJ);
1174-
CUnsignedVGPMessage unsignedMessage(message.vchMsg);
1186+
CUnsignedVGPMessage unsignedMessage(messageWrapper.vchMsg);
11751187
oMessage.push_back(Pair("sender_fqdn", stringFromVch(unsignedMessage.SenderFQDN())));
11761188
oMessage.push_back(Pair("type", stringFromVch(unsignedMessage.Type())));
11771189
oMessage.push_back(Pair("message", stringFromVch(unsignedMessage.Value())));
11781190
oMessage.push_back(Pair("message_id", unsignedMessage.MessageID.ToString()));
1179-
oMessage.push_back(Pair("message_size", (int)unsignedMessage.Value().size()));
1191+
oMessage.push_back(Pair("message_size", (int)messageWrapper.vchMsg.size()));
11801192
oMessage.push_back(Pair("timestamp_epoch", unsignedMessage.nTimeStamp));
11811193
oMessage.push_back(Pair("record_num", (int)nCounter));
1182-
oMessages.push_back(Pair(message.GetHash().ToString(), oMessage));
1194+
oMessages.push_back(Pair(messageWrapper.GetHash().ToString(), oMessage));
11831195
nCounter++;
11841196
}
11851197
}

src/bdap/vgpmessage.cpp

Lines changed: 54 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -40,14 +40,15 @@ class CMessage
4040
std::vector<unsigned char> vchMessageType;
4141
std::vector<unsigned char> vchMessage;
4242
std::vector<unsigned char> vchSenderFQDN;
43+
bool fKeepLast;
4344

4445
CMessage()
4546
{
4647
SetNull();
4748
}
4849

49-
CMessage(const int& version, const std::vector<unsigned char>& type, const std::vector<unsigned char>& message, const std::vector<unsigned char>& sender)
50-
: nMessageVersion(version), vchMessageType(type), vchMessage(message), vchSenderFQDN(sender) {}
50+
CMessage(const int& version, const std::vector<unsigned char>& type, const std::vector<unsigned char>& message, const std::vector<unsigned char>& sender, bool keeplast)
51+
: nMessageVersion(version), vchMessageType(type), vchMessage(message), vchSenderFQDN(sender), fKeepLast(keeplast) {}
5152

5253
CMessage(const std::vector<unsigned char>& vchData)
5354
{
@@ -63,6 +64,7 @@ class CMessage
6364
READWRITE(vchMessageType);
6465
READWRITE(vchMessage);
6566
READWRITE(vchSenderFQDN);
67+
READWRITE(fKeepLast);
6668
}
6769

6870
void SetNull()
@@ -71,6 +73,7 @@ class CMessage
7173
vchMessageType.clear();
7274
vchMessage.clear();
7375
vchSenderFQDN.clear();
76+
fKeepLast = false;
7477
}
7578

7679
inline bool IsNull() const { return (nMessageVersion == -1); }
@@ -81,6 +84,7 @@ class CMessage
8184
vchMessageType = b.vchMessageType;
8285
vchMessage = b.vchMessage;
8386
vchSenderFQDN = b.vchSenderFQDN;
87+
fKeepLast = b.fKeepLast;
8488
return *this;
8589
}
8690

@@ -143,9 +147,9 @@ std::string CUnsignedVGPMessage::ToString() const
143147
}
144148

145149
bool CUnsignedVGPMessage::EncryptMessage(const std::vector<unsigned char>& vchType, const std::vector<unsigned char>& vchMessage, const std::vector<unsigned char>& vchSenderFQDN,
146-
const std::vector<std::vector<unsigned char>>& vvchPubKeys, std::string& strErrorMessage)
150+
const std::vector<std::vector<unsigned char>>& vvchPubKeys, const bool fKeepLast, std::string& strErrorMessage)
147151
{
148-
CMessage message(1, vchType, vchMessage, vchSenderFQDN);
152+
CMessage message(1, vchType, vchMessage, vchSenderFQDN, fKeepLast);
149153
std::vector<unsigned char> vchData;
150154
message.Serialize(vchData);
151155
std::vector<unsigned char> vchCipherText;
@@ -158,7 +162,7 @@ bool CUnsignedVGPMessage::EncryptMessage(const std::vector<unsigned char>& vchTy
158162
return true;
159163
}
160164

161-
bool CUnsignedVGPMessage::DecryptMessage(const std::array<char, 32>& arrPrivateSeed, std::vector<unsigned char>& vchType, std::vector<unsigned char>& vchMessage, std::vector<unsigned char>& vchSenderFQDN, std::string& strErrorMessage)
165+
bool CUnsignedVGPMessage::DecryptMessage(const std::array<char, 32>& arrPrivateSeed, std::vector<unsigned char>& vchType, std::vector<unsigned char>& vchMessage, std::vector<unsigned char>& vchSenderFQDN, bool& fKeepLast, std::string& strErrorMessage)
162166
{
163167
if (!fEncrypted)
164168
return false;
@@ -177,6 +181,7 @@ bool CUnsignedVGPMessage::DecryptMessage(const std::array<char, 32>& arrPrivateS
177181
vchType = message.vchMessageType;
178182
vchMessage = message.vchMessage;
179183
vchSenderFQDN = message.vchSenderFQDN;
184+
fKeepLast = message.fKeepLast;
180185
return true;
181186
}
182187

@@ -229,6 +234,16 @@ std::vector<unsigned char> CUnsignedVGPMessage::SenderFQDN()
229234
return message.vchSenderFQDN;
230235
}
231236

237+
bool CUnsignedVGPMessage::KeepLast()
238+
{
239+
bool keepLast = false;
240+
if (fEncrypted)
241+
return keepLast;
242+
243+
CMessage message(vchMessageData);
244+
return message.fKeepLast;
245+
}
246+
232247
CVGPMessage::CVGPMessage(CUnsignedVGPMessage& unsignedMessage)
233248
{
234249
unsignedMessage.Serialize(vchMsg);
@@ -485,11 +500,12 @@ bool DecryptMessage(CUnsignedVGPMessage& unsignedMessage)
485500
std::string strErrorMessage = "";
486501
if (GetSharedPrivateSeed(link, seed, strErrorMessage))
487502
{
503+
bool fKeepLast;
488504
std::vector<unsigned char> vchType, vchMessage, vchSenderFQDN;
489-
if (unsignedMessage.DecryptMessage(seed, vchType, vchMessage, vchSenderFQDN, strErrorMessage))
505+
if (unsignedMessage.DecryptMessage(seed, vchType, vchMessage, vchSenderFQDN, fKeepLast, strErrorMessage))
490506
{
491507
LogPrint("bdap", "%s -- Found and decrypted type = %s, message = %s, sender = %s\n", __func__, stringFromVch(vchType), stringFromVch(vchMessage), stringFromVch(vchSenderFQDN));
492-
CMessage message(1, vchType, vchMessage, vchSenderFQDN);
508+
CMessage message(1, vchType, vchMessage, vchSenderFQDN, fKeepLast);
493509
unsignedMessage.fEncrypted = false;
494510
message.Serialize(unsignedMessage.vchMessageData);
495511
return true;
@@ -560,10 +576,11 @@ void GetMyLinkMessages(const uint256& subjectID, std::vector<CUnsignedVGPMessage
560576
vMessages.push_back(unsignedMessage);
561577
}
562578
}
579+
itr++;
563580
}
564581
}
565582

566-
void GetMyLinkMessagesByType(const std::vector<unsigned char>& vchType, const std::vector<unsigned char>& vchRecipientFQDN, std::vector<CVGPMessage>& vMessages)
583+
void GetMyLinkMessagesByType(const std::vector<unsigned char>& vchType, const std::vector<unsigned char>& vchRecipientFQDN, std::vector<CVGPMessage>& vMessages, bool& fKeepLast)
567584
{
568585
LOCK(cs_mapMyVGPMessages);
569586
std::map<uint256, CVGPMessage>::iterator itr = mapMyVGPMessages.begin();
@@ -577,6 +594,9 @@ void GetMyLinkMessagesByType(const std::vector<unsigned char>& vchType, const st
577594
}
578595
if (!unsignedMessage.fEncrypted && (vchType.size() == 0 || vchType == unsignedMessage.Type()) && unsignedMessage.SenderFQDN() != vchRecipientFQDN)
579596
{
597+
if (unsignedMessage.KeepLast())
598+
fKeepLast = true;
599+
580600
vMessages.push_back(unsignedMessage);
581601
}
582602
itr++;
@@ -598,4 +618,30 @@ void GetMyLinkMessagesBySubjectAndSender(const uint256& subjectID, const std::ve
598618
}
599619
itr++;
600620
}
621+
}
622+
623+
void KeepLastBySender(std::vector<CVGPMessage>& vMessages)
624+
{
625+
std::map<std::vector<unsigned char>, std::pair<CVGPMessage, int64_t> > mapFromMessageTime;
626+
for (const CVGPMessage& message : vMessages)
627+
{
628+
CUnsignedVGPMessage unsignedMessage(message.vchMsg);
629+
if (!unsignedMessage.fEncrypted)
630+
{
631+
std::map<std::vector<unsigned char>, std::pair<CVGPMessage, int64_t> >::iterator itFind = mapFromMessageTime.find(unsignedMessage.SenderFQDN());
632+
if (itFind == mapFromMessageTime.end()) {
633+
mapFromMessageTime[unsignedMessage.SenderFQDN()] = std::make_pair(message, unsignedMessage.nTimeStamp);
634+
}
635+
else if (unsignedMessage.nTimeStamp > itFind->second.second) {
636+
mapFromMessageTime[unsignedMessage.SenderFQDN()] = std::make_pair(message, unsignedMessage.nTimeStamp);
637+
}
638+
}
639+
}
640+
vMessages.clear();
641+
std::map<std::vector<unsigned char>, std::pair<CVGPMessage, int64_t> >::iterator itr = mapFromMessageTime.begin();
642+
while (itr != mapFromMessageTime.end())
643+
{
644+
vMessages.push_back(itr->second.first);
645+
itr++;
646+
}
601647
}

src/bdap/vgpmessage.h

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@ class CUnsignedVGPMessage
4747
int64_t nTimeStamp;
4848
int64_t nRelayUntil; // when newer nodes stop relaying to newer nodes
4949
std::vector<unsigned char> vchMessageData;
50+
5051

5152
CUnsignedVGPMessage(const uint256& subjectID, const uint256& messageID, const std::vector<unsigned char> wallet, int64_t timestamp, int64_t stoptime)
5253
: SubjectID(subjectID), MessageID(messageID), vchWalletPubKey(wallet), nTimeStamp(timestamp), nRelayUntil(stoptime)
@@ -109,14 +110,15 @@ class CUnsignedVGPMessage
109110
void SetNull();
110111

111112
bool EncryptMessage(const std::vector<unsigned char>& vchType, const std::vector<unsigned char>& vchMessage, const std::vector<unsigned char>& vchSenderFQDN,
112-
const std::vector<std::vector<unsigned char>>& vvchPubKeys, std::string& strErrorMessage);
113+
const std::vector<std::vector<unsigned char>>& vvchPubKeys, const bool fKeepLast, std::string& strErrorMessage);
113114

114115
bool DecryptMessage(const std::array<char, 32>& arrPrivateSeed, std::vector<unsigned char>& vchType,
115-
std::vector<unsigned char>& vchMessage, std::vector<unsigned char>& vchSenderFQDN, std::string& strErrorMessage);
116+
std::vector<unsigned char>& vchMessage, std::vector<unsigned char>& vchSenderFQDN, bool& fKeepLast, std::string& strErrorMessage);
116117

117118
std::vector<unsigned char> Type();
118119
std::vector<unsigned char> Value();
119120
std::vector<unsigned char> SenderFQDN();
121+
bool KeepLast();
120122
std::string ToString() const;
121123

122124
};
@@ -179,8 +181,9 @@ void CleanupMyMessageMap();
179181
bool DecryptMessage(CUnsignedVGPMessage& unsignedMessage);
180182
void AddMyMessage(const CVGPMessage& message);
181183
void GetMyLinkMessages(const uint256& subjectID, std::vector<CUnsignedVGPMessage>& vMessages);
182-
void GetMyLinkMessagesByType(const std::vector<unsigned char>& vchType, const std::vector<unsigned char>& vchRecipientFQDN, std::vector<CVGPMessage>& vMessages);
184+
void GetMyLinkMessagesByType(const std::vector<unsigned char>& vchType, const std::vector<unsigned char>& vchRecipientFQDN, std::vector<CVGPMessage>& vMessages, bool& fKeepLast);
183185
void GetMyLinkMessagesBySubjectAndSender(const uint256& subjectID, const std::vector<unsigned char>& vchSenderFQDN,
184186
const std::vector<unsigned char>& vchType, std::vector<CVGPMessage>& vchMessages);
187+
void KeepLastBySender(std::vector<CVGPMessage>& vMessages);
185188

186189
#endif // DYNAMIC_BDAP_RELAYMESSAGE_H

src/test/bdap_vgp_message_tests.cpp

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -228,7 +228,7 @@ BOOST_AUTO_TEST_CASE(bdap_vgp_message_test1)
228228
CUnsignedVGPMessage unsignedMessage(subjectID, messageID, bcastvchWalletPubKey, timestamp, stoptime);
229229

230230
//test that we can encrypt the message
231-
BOOST_CHECK(unsignedMessage.EncryptMessage(vchMessageType, vchMessage, vchRequestorFQDN, vvchPubKeys, strErrorMessage));
231+
BOOST_CHECK(unsignedMessage.EncryptMessage(vchMessageType, vchMessage, vchRequestorFQDN, vvchPubKeys, false, strErrorMessage));
232232

233233
//setup message for broadcast
234234
CVGPMessage vpgMessage(unsignedMessage);
@@ -247,12 +247,12 @@ BOOST_AUTO_TEST_CASE(bdap_vgp_message_test1)
247247

248248
std::vector<unsigned char> retrievedvchType, retrievedvchMessage, retrievedvchSenderFQDN;
249249

250-
250+
bool fKeepLast = false;
251251
//shouldn't decrypt with wrong seed
252-
BOOST_CHECK(unsignedMessage.DecryptMessage(invalidseed, retrievedvchType, retrievedvchMessage, retrievedvchSenderFQDN, strErrorMessage2) == false);
252+
BOOST_CHECK(unsignedMessage.DecryptMessage(invalidseed, retrievedvchType, retrievedvchMessage, retrievedvchSenderFQDN, fKeepLast, strErrorMessage2) == false);
253253

254254
//decrypt with proper seed
255-
BOOST_CHECK(unsignedMessage.DecryptMessage(seed1, retrievedvchType, retrievedvchMessage, retrievedvchSenderFQDN, strErrorMessage2));
255+
BOOST_CHECK(unsignedMessage.DecryptMessage(seed1, retrievedvchType, retrievedvchMessage, retrievedvchSenderFQDN, fKeepLast, strErrorMessage2));
256256

257257
//message values should match (original vs decrypted retrieved value)
258258
BOOST_CHECK(vchMessage == retrievedvchMessage);

0 commit comments

Comments
 (0)