Skip to content

Commit 90eb1eb

Browse files
committed
[BDAP] Add hash proof for spam protection to VGP messages
1 parent 569898c commit 90eb1eb

File tree

3 files changed

+69
-6
lines changed

3 files changed

+69
-6
lines changed

src/bdap/rpclinking.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1087,9 +1087,9 @@ static UniValue SendMessage(const JSONRPCRequest& request)
10871087
oLink.push_back(Pair("shared_pubkey", key.GetPubKeyString()));
10881088
oLink.push_back(Pair("subject_id", unsignedMessage.SubjectID.ToString()));
10891089
oLink.push_back(Pair("message_id", unsignedMessage.MessageID.ToString()));
1090+
vpgMessage.MineMessage();
10901091
oLink.push_back(Pair("message_hash", vpgMessage.GetHash().ToString()));
10911092
oLink.push_back(Pair("message_size", (int)vpgMessage.vchMsg.size()));
1092-
10931093
vpgMessage.Sign(walletKey);
10941094
oLink.push_back(Pair("signature_size", (int)vpgMessage.vchSig.size()));
10951095
if (vpgMessage.CheckSignature(vchWalletPubKey)) {

src/bdap/vgpmessage.cpp

Lines changed: 57 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -121,6 +121,7 @@ void CUnsignedVGPMessage::SetNull()
121121
nTimeStamp = 0;
122122
nRelayUntil = 0;
123123
vchMessageData.clear();
124+
nNonce = 0;
124125
}
125126

126127
std::string CUnsignedVGPMessage::ToString() const
@@ -135,6 +136,8 @@ std::string CUnsignedVGPMessage::ToString() const
135136
" nTimeStamp = %d\n"
136137
" nRelayUntil = %d\n"
137138
" Message Size = %d\n"
139+
" nNonce = %d\n"
140+
" Hash = %s\n"
138141
")\n",
139142
nVersion,
140143
SubjectID.ToString(),
@@ -143,7 +146,17 @@ std::string CUnsignedVGPMessage::ToString() const
143146
stringFromVch(vchWalletPubKey),
144147
nTimeStamp,
145148
nRelayUntil,
146-
vchMessageData.size());
149+
vchMessageData.size(),
150+
nNonce,
151+
GetHash().ToString()
152+
);
153+
}
154+
155+
uint256 CUnsignedVGPMessage::GetHash() const
156+
{
157+
CDataStream dsMessageData(SER_NETWORK, PROTOCOL_VERSION);
158+
dsMessageData << *this;
159+
return hash_Argon2d(dsMessageData.begin(), dsMessageData.end(), 1);
147160
}
148161

149162
bool CUnsignedVGPMessage::EncryptMessage(const std::vector<unsigned char>& vchType, const std::vector<unsigned char>& vchMessage, const std::vector<unsigned char>& vchSenderFQDN,
@@ -249,6 +262,14 @@ CVGPMessage::CVGPMessage(CUnsignedVGPMessage& unsignedMessage)
249262
unsignedMessage.Serialize(vchMsg);
250263
}
251264

265+
int CVGPMessage::Version() const
266+
{
267+
if (vchMsg.size() == 0)
268+
return -1;
269+
270+
return CUnsignedVGPMessage(vchMsg).nVersion;
271+
}
272+
252273
void CVGPMessage::SetNull()
253274
{
254275
vchMsg.clear();
@@ -262,7 +283,11 @@ bool CVGPMessage::IsNull() const
262283

263284
uint256 CVGPMessage::GetHash() const
264285
{
265-
return Hash(this->vchMsg.begin(), this->vchMsg.end());
286+
CUnsignedVGPMessage unsignedMessage(vchMsg);
287+
if (unsignedMessage.nVersion == 1)
288+
return Hash(this->vchMsg.begin(), this->vchMsg.end());
289+
290+
return unsignedMessage.GetHash();
266291
}
267292

268293
bool CVGPMessage::IsInEffect() const
@@ -366,6 +391,12 @@ int CVGPMessage::ProcessMessage(std::string& strErrorMessage) const
366391
strErrorMessage = "VGP message has an invalid signature. Adding 100 to ban score.";
367392
return 100; // this will add 100 to the peer's ban score
368393
}
394+
if (unsignedMessage.nVersion > 1 && UintToArith256(unsignedMessage.GetHash()) > UintToArith256(VGP_MESSAGE_MIN_HASH_TARGET))
395+
{
396+
LogPrintf("%s -- message %s\n", __func__, unsignedMessage.ToString());
397+
strErrorMessage = "Message proof of work is invalid and under the target.";
398+
return 100; // this will add 100 to the peer's ban score
399+
}
369400
// check if message is for me. if, validate MessageID. If MessageID validates okay, store in memory map.
370401
int nMyLinkStatus = pLinkManager->IsMyMessage(unsignedMessage.SubjectID, unsignedMessage.MessageID, unsignedMessage.nTimeStamp);
371402
if (nMyLinkStatus == 1)
@@ -403,6 +434,30 @@ bool CVGPMessage::RelayTo(CNode* pnode, CConnman& connman) const
403434
return true;
404435
}
405436

437+
void CVGPMessage::MineMessage()
438+
{
439+
int64_t nStart = GetTimeMillis();
440+
CUnsignedVGPMessage message(vchMsg);
441+
message.nNonce = 0;
442+
arith_uint256 besthash = UintToArith256(uint256S("ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"));
443+
arith_uint256 hashTarget = UintToArith256(VGP_MESSAGE_MIN_HASH_TARGET);
444+
arith_uint256 newhash = UintToArith256(message.GetHash());
445+
while (newhash > hashTarget) {
446+
message.nNonce++;
447+
if (message.nNonce == 0) {
448+
++message.nTimeStamp;
449+
++message.nRelayUntil;
450+
}
451+
if (newhash < besthash) {
452+
besthash = newhash;
453+
LogPrint("bdap", "%s -- New best: %s\n", __func__, newhash.GetHex());
454+
}
455+
newhash = UintToArith256(message.GetHash());
456+
}
457+
message.Serialize(vchMsg);
458+
LogPrintf("%s -- Milliseconds %d, nNonce %d, Hash %s\n", __func__, GetTimeMillis() - nStart, message.nNonce, GetHash().ToString());
459+
}
460+
406461
bool GetSecretSharedKey(const std::string& strSenderFQDN, const std::string& strRecipientFQDN, CKeyEd25519& key, std::string& strErrorMessage)
407462
{
408463
if (!pLinkManager)

src/bdap/vgpmessage.h

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,6 @@ class CKey;
2222
class CKeyEd25519;
2323
class CNode;
2424
class CVGPMessage;
25-
class uint256;
2625

2726
static constexpr size_t MAX_MESSAGE_SIZE = 8192;
2827
static constexpr int MIN_VGP_MESSAGE_PEER_PROTO_VERSION = 71200; // TODO (BDAP): Update minimum protocol version before v2.4 release
@@ -34,11 +33,15 @@ static constexpr int KEEP_MESSAGE_LOG_ALIVE_SECONDS = 300; // 5 minutes.
3433
static constexpr int KEEP_MY_MESSAGE_ALIVE_SECONDS = 240; // 4 minutes.
3534
static constexpr int MAX_MESAGGE_DRIFT_SECONDS = 90; // 1.5 minutes.
3635
static constexpr int MAX_MESAGGE_RELAY_SECONDS = 120; // 2 minutes.
36+
static const uint256 VGP_MESSAGE_MIN_HASH_TARGET = uint256S("00ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff");
3737

38+
// TODO (BDAP): do not support v1 messages or change hash proof message to v1.
39+
//! Version VPG message 1 doesn't contain hash proof to prevent spam
40+
//! Version 2 requires hash proof
3841
class CUnsignedVGPMessage
3942
{
4043
public:
41-
static const int CURRENT_VERSION = 1;
44+
static const int CURRENT_VERSION = 2;
4245
int nVersion;
4346
uint256 SubjectID;
4447
uint256 MessageID; // derived by hashing the public key + nTimestamp
@@ -47,7 +50,7 @@ class CUnsignedVGPMessage
4750
int64_t nTimeStamp;
4851
int64_t nRelayUntil; // when newer nodes stop relaying to newer nodes
4952
std::vector<unsigned char> vchMessageData;
50-
53+
uint32_t nNonce;
5154

5255
CUnsignedVGPMessage(const uint256& subjectID, const uint256& messageID, const std::vector<unsigned char> wallet, int64_t timestamp, int64_t stoptime)
5356
: SubjectID(subjectID), MessageID(messageID), vchWalletPubKey(wallet), nTimeStamp(timestamp), nRelayUntil(stoptime)
@@ -79,6 +82,7 @@ class CUnsignedVGPMessage
7982
READWRITE(nTimeStamp);
8083
READWRITE(nRelayUntil);
8184
READWRITE(vchMessageData);
85+
READWRITE(nNonce);
8286
}
8387

8488
inline CUnsignedVGPMessage operator=(const CUnsignedVGPMessage& b)
@@ -91,6 +95,7 @@ class CUnsignedVGPMessage
9195
nTimeStamp = b.nTimeStamp;
9296
nRelayUntil = b.nRelayUntil;
9397
vchMessageData = b.vchMessageData;
98+
nNonce = b.nNonce;
9499
return *this;
95100
}
96101

@@ -120,6 +125,7 @@ class CUnsignedVGPMessage
120125
std::vector<unsigned char> SenderFQDN();
121126
bool KeepLast();
122127
std::string ToString() const;
128+
uint256 GetHash() const;
123129

124130
};
125131

@@ -169,6 +175,8 @@ class CVGPMessage
169175
bool CheckSignature(const std::vector<unsigned char>& vchPubKey) const;
170176
int ProcessMessage(std::string& strErrorMessage) const;
171177
bool RelayTo(CNode* pnode, CConnman& connman) const;
178+
int Version() const;
179+
void MineMessage();
172180

173181
};
174182

0 commit comments

Comments
 (0)