Skip to content

Commit

Permalink
verify node at IP before send commitment
Browse files Browse the repository at this point in the history
Signed-off-by: crptec <crptec.fr@gmail.com>
  • Loading branch information
crptec committed Mar 27, 2020
1 parent 850c88f commit 117a041
Show file tree
Hide file tree
Showing 3 changed files with 194 additions and 325 deletions.
247 changes: 190 additions & 57 deletions src/infinitynodelockreward.cpp
Expand Up @@ -44,7 +44,7 @@ bool CLockRewardRequest::Sign(const CKey& keyInfinitynode, const CPubKey& pubKey
}

if(!CMessageSigner::VerifyMessage(pubKeyInfinitynode, vchSig, strMessage, strError)) {
LogPrintf("CMasternodePing::Sign -- VerifyMessage() failed, error: %s\n", strError);
LogPrintf("CLockRewardRequest::Sign -- VerifyMessage() failed, error: %s\n", strError);
return false;
}

Expand All @@ -59,7 +59,7 @@ bool CLockRewardRequest::CheckSignature(CPubKey& pubKeyInfinitynode, int &nDos)
std::string strError = "";

if(!CMessageSigner::VerifyMessage(pubKeyInfinitynode, vchSig, strMessage, strError)) {
LogPrintf("CMasternodePing::CheckSignature -- Got bad Infinitynode LockReward signature, ID=%s, error: %s\n",
LogPrintf("CLockRewardRequest::CheckSignature -- Got bad Infinitynode LockReward signature, ID=%s, error: %s\n",
burnTxIn.prevout.ToStringShort(), strError);
/*TODO: set ban value befor release*/
nDos = 0;
Expand All @@ -81,7 +81,7 @@ bool CLockRewardRequest::IsValid(CNode* pnode, int nValidationHeight, std::strin
return false;
}

int nDos = 0;
int nDos = 20;
CMetadata meta = infnodemeta.Find(inf.getMetaID());
std::string metaPublicKey = meta.getMetaPublicKey();
std::vector<unsigned char> tx_data = DecodeBase64(metaPublicKey.c_str());
Expand Down Expand Up @@ -161,9 +161,6 @@ bool CInfinityNodeLockReward::GetLockRewardRequest(const uint256& reqHash, CLock
return true;
}

/*
* find old request which has the same nRewardHeight, burnTxIn, nSINtype, nLoop inferior => remove it
*/
void CInfinityNodeLockReward::RemoveLockRewardRequest(const CLockRewardRequest& lockRewardRequest)
{
AssertLockHeld(cs);
Expand All @@ -181,26 +178,99 @@ void CInfinityNodeLockReward::RemoveLockRewardRequest(const CLockRewardRequest&
}
}

bool CInfinityNodeLockReward::ProcessLockRewardRequest(CNode* pfrom, CLockRewardRequest& lockRewardRequestRet, CConnman& connman, int nBlockHeight)
/*
* STEP 1: get a new LockRewardRequest, check it and send verify message
*
* STEP 1.1 check LockRewardRequest is valid or NOT
* - the nHeight of request cannot be lower than current height
* - the nHeight of request cannot so far in future ( currentHeight + Params().GetConsensus().nInfinityNodeCallLockRewardDeepth + 2)
* - the LockRewardRequest must be valid
* + from (nHeight, SINtype) => find candidate
* + CTxIn of request and CTxIn of candidate must be identical
* + Find publicKey of Candidate in metadata and check the signature in request
*/
bool CInfinityNodeLockReward::CheckLockRewardRequest(CNode* pfrom, CLockRewardRequest& lockRewardRequestRet, CConnman& connman, int nBlockHeight)
{
AssertLockHeld(cs);
if(lockRewardRequestRet.nRewardHeight > nBlockHeight + Params().GetConsensus().nInfinityNodeCallLockRewardDeepth + 2
|| lockRewardRequestRet.nRewardHeight < nBlockHeight){
LogPrintf("CInfinityNodeLockReward::ProcessLockRewardRequest -- LockRewardRequest for invalid height: %d, current height: %d\n", lockRewardRequestRet.nRewardHeight, nBlockHeight);
LogPrintf("CInfinityNodeLockReward::CheckLockRewardRequest -- LockRewardRequest for invalid height: %d, current height: %d\n",
lockRewardRequestRet.nRewardHeight, nBlockHeight);
return false;
}

std::string strError = "";
if(!lockRewardRequestRet.IsValid(pfrom, nBlockHeight, strError, connman)){
LogPrintf("CInfinityNodeLockReward::ProcessLockRewardRequest -- LockRewardRequest is invalid. ERROR: %s\n",strError);
LogPrintf("CInfinityNodeLockReward::CheckLockRewardRequest -- LockRewardRequest is invalid. ERROR: %s\n",strError);
return false;
}

return true;
}

/*
* send verify request to Candidate A at IP(addr) for Request(lockRewardRequestRet)
* STEP 1: get a new LockRewardRequest, check it and send verify message
*
* STEP 1.2 verify candidate
*/

bool CInfinityNodeLockReward::VerifyLockRewardCandidate(CLockRewardRequest& lockRewardRequestRet, CConnman& connman)
{
AssertLockHeld(cs);
//step 1.2.1: chech if mypeer is good candidate to make Musig
CInfinitynode infRet;
if(!infnodeman.Get(infinitynodePeer.burntx, infRet)){
LogPrintf("CInfinityNodeLockReward::VerifyLockRewardCandidate -- Can not identify mypeer in list, height: %d\n");
return false;
}

int nScore;

if(!infnodeman.getNodeScoreAtHeight(infinitynodePeer.burntx, lockRewardRequestRet.nRewardHeight - 101, nScore)) {
LogPrintf("CMasternodePaymentVote::VerifyLockRewardCandidate -- Can't calculate score for Infinitynode %s\n",
infinitynodePeer.burntx.ToStringShort());
return false;
}

//step 1.2.2: if my score is in Top, i will verify that candidate is online at IP

//step 1.2.2.1: get InfCandidate from request
CInfinitynode infCandidate;
if(!infnodeman.Get(lockRewardRequestRet.burnTxIn.prevout, infCandidate)){
LogPrintf("CInfinityNodeLockReward::VerifyLockRewardCandidate -- Cannot identify candidate in list\n");
return false;
}

CMetadata metaCandidate = infnodemeta.Find(infCandidate.getMetaID());
if(metaCandidate.getMetadataHeight() == 0){
LogPrintf("CInfinityNodeLockReward::VerifyLockRewardCandidate -- Cannot get metadata of candidate %s\n", infCandidate.getBurntxOutPoint().ToStringShort());
return false;
}

CService candidateService = metaCandidate.getService();
if(!SendVerifyRequest(CAddress(candidateService, NODE_NETWORK), infinitynodePeer.burntx, lockRewardRequestRet, connman)){
LogPrintf("CInfinityNodeLockReward::VerifyLockRewardCandidate -- Cannot send verify message to candidate %s\n", infCandidate.getBurntxOutPoint().ToStringShort());
return false;
}

return true;
//TODO:
/*
if(nScore < Params().GetConsensus().nInfinityNodeLockRewardTop) {
//step 2.1: verify node which send the request is online at IP in metadata
//SendVerifyRequest()
//step 2.2: send commitment
return true;
} else {
LogPrintf("CMasternodePaymentVote::VerifyLockRewardCandidate -- I am not in Top score\n");
return false;
}*/
}

/*
* STEP 1: get a new LockRewardRequest, check it and send verify message
*
* STEP 1.3 send verify request to Candidate A at IP(addr) for Request(lockRewardRequestRet)
*/
bool CInfinityNodeLockReward::SendVerifyRequest(const CAddress& addr, COutPoint myPeerBurnTx, CLockRewardRequest& lockRewardRequestRet, CConnman& connman)
{
Expand All @@ -209,14 +279,14 @@ bool CInfinityNodeLockReward::SendVerifyRequest(const CAddress& addr, COutPoint
std::string strMessage = strprintf("%s%d%s", myPeerBurnTx.ToString(), vrequest.nonce, lockRewardRequestRet.GetHash().ToString());

if(!CMessageSigner::SignMessage(strMessage, vrequest.vchSig1, infinitynodePeer.keyInfinitynode)) {
LogPrintf("CInfinityNodeLockReward::SendVerifyReply -- SignMessage() failed\n");
LogPrintf("CInfinityNodeLockReward::SendVerifyRequest -- SignMessage() failed\n");
return false;
}

std::string strError;

if(!CMessageSigner::VerifyMessage(infinitynodePeer.pubKeyInfinitynode, vrequest.vchSig1, strMessage, strError)) {
LogPrintf("CInfinityNodeLockReward::SendVerifyReply -- VerifyMessage() failed, error: %s\n", strError);
LogPrintf("CInfinityNodeLockReward::SendVerifyRequest -- VerifyMessage() failed, error: %s\n", strError);
return false;
}

Expand All @@ -233,69 +303,90 @@ bool CInfinityNodeLockReward::SendVerifyRequest(const CAddress& addr, COutPoint
return true;
}

bool CInfinityNodeLockReward::ProcessLockRewardCommitment(CLockRewardRequest& lockRewardRequestRet, CConnman& connman)
/*
* STEP 2: get a verify message, check and try to answer the message
*
* check:
* - VerifyRequest was sent from Top Node
* - Signature of VerifyRequest is correct
* answer:
* - create the 2nd signature - my signature and send back to node
* processVerifyRequestReply:
* - check 2nd signature
* - disconnect to node ( Candidate )
*/
//TODO: ban pnode if false
bool CInfinityNodeLockReward::SendVerifyReply(CNode* pnode, CVerifyRequest& vrequest, CConnman& connman)
{
// only Infinitynode will answer the verify requrest
if(!fInfinityNode) {return false;}

AssertLockHeld(cs);
//step 1: chech if mypeer is good candidate to make Musig
CInfinitynode infRet;
if(!infnodeman.Get(infinitynodePeer.burntx, infRet)){
LogPrintf("CInfinityNodeLockReward::ProcessLockRewardCommitment -- Can not identify mypeer in list, height: %d\n");

//step 2.0 get publicKey of sender and check signature
infinitynode_info_t infoInf;
if(!infnodeman.GetInfinitynodeInfo(vrequest.vin1.prevout, infoInf)){
LogPrintf("CInfinityNodeLockReward::SendVerifyReply -- Cannot find sender from list %s\n");
return false;
}

int nScore;
CMetadata metaSender = infnodemeta.Find(infoInf.metadataID);
if (metaSender.getMetadataHeight() == 0){
LogPrintf("CInfinityNodeLockReward::SendVerifyReply -- Cannot find sender from list %s\n");
return false;
}

if(!infnodeman.getNodeScoreAtHeight(infinitynodePeer.burntx, lockRewardRequestRet.nRewardHeight - 101, nScore)) {
LogPrintf("CMasternodePaymentVote::ProcessLockRewardCommitment -- Can't calculate score for Infinitynode %s\n",
infinitynodePeer.burntx.ToStringShort());
std::string metaPublicKey = metaSender.getMetaPublicKey();
std::vector<unsigned char> tx_data = DecodeBase64(metaPublicKey.c_str());
CPubKey pubKey(tx_data.begin(), tx_data.end());

std::string strError;
std::string strMessage = strprintf("%s%d%s", vrequest.vin1.prevout.ToString(), vrequest.nonce, vrequest.nHashRequest.ToString());
if(!CMessageSigner::VerifyMessage(pubKey, vrequest.vchSig1, strMessage, strError)) {
LogPrintf("CInfinityNodeLockReward::SendVerifyReply -- VerifyMessage() failed, error: %s, message: \n", strError, strMessage);
return false;
}

//step 2: if my score is in Top, i can send commitment to build Musig
if(nScore < Params().GetConsensus().nInfinityNodeLockRewardTop) {
//step 2.1: verify node which send the request is online at IP in metadata
//SendVerifyRequest()
//step 2.2: send commitment
return true;
} else {
LogPrintf("CMasternodePaymentVote::ProcessLockRewardCommitment -- I am not in Top score\n");
//step 2.1 check if sender in Top (skip this step for now)

//step 2.2 sign a new message and send it back to sender
vrequest.addr = infinitynodePeer.service;
vrequest.vin2 = CTxIn(infinitynodePeer.burntx);
std::string strMessage2 = strprintf("%s%d%s%s%s", vrequest.addr.ToString(false), vrequest.nonce, vrequest.nHashRequest.ToString(),
vrequest.vin1.prevout.ToStringShort(), vrequest.vin2.prevout.ToStringShort());

if(!CMessageSigner::SignMessage(strMessage2, vrequest.vchSig2, infinitynodePeer.keyInfinitynode)) {
LogPrintf("CInfinityNodeLockReward::ProcessVerifyReply -- SignMessage() failed\n");
return false;
}

if(!CMessageSigner::VerifyMessage(infinitynodePeer.pubKeyInfinitynode, vrequest.vchSig2, strMessage2, strError)) {
LogPrintf("CInfinityNodeLockReward::ProcessVerifyReply -- VerifyMessage() failed, error: %s\n", strError);
return false;
}

connman.PushMessage(pnode, CNetMsgMaker(pnode->GetSendVersion()).Make(NetMsgType::INFVERIFY, vrequest));
return true;
}

void CInfinityNodeLockReward::ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStream& vRecv, CConnman& connman)
/*
* STEP 3: check return VerifyRequest, if it is OK then
* - send the commitment
* - disconect node
*/
bool CInfinityNodeLockReward::CheckVerifyReply(CNode* pnode, CVerifyRequest& vrequest)
{
if(fLiteMode) return; // disable all SIN specific functionality
if (strCommand == NetMsgType::INFLOCKREWARDINIT) {
CLockRewardRequest lockReq;
vRecv >> lockReq;
//dont ask pfrom for this Request anymore
uint256 nHash = lockReq.GetHash();
pfrom->setAskFor.erase(nHash);
{
LOCK(cs);
if(mapLockRewardRequest.count(nHash)) return;
if(!ProcessLockRewardRequest(pfrom, lockReq, connman, nCachedBlockHeight)){
return;
}
LogPrintf("CInfinityNodeLockReward::ProcessMessage -- add new LockRewardRequest from %d\n",pfrom->GetId());
if(AddLockRewardRequest(lockReq)){
lockReq.Relay(connman);
if(!ProcessLockRewardCommitment(lockReq, connman)){
LogPrintf("CInfinityNodeLockReward::ProcessMessage -- can not send commitment. May be i am not in Top score.\n");
return;
}
}
return;
}
}
pnode->fDisconnect = true;
}

/*
* STEP 0: create LockRewardRequest if i am a candidate at nHeight
*/
bool CInfinityNodeLockReward::ProcessBlock(int nBlockHeight, CConnman& connman)
{
if(fLiteMode || !fInfinityNode) return false;

//step 1: Check if this InfinitynodePeer is a candidate at nBlockHeight
//step 0.1: Check if this InfinitynodePeer is a candidate at nBlockHeight
CInfinitynode infRet;
if(!infnodeman.Get(infinitynodePeer.burntx, infRet)){
LogPrintf("CInfinityNodeLockReward::ProcessBlock -- Can not identify mypeer in list, height: %d\n", nBlockHeight);
Expand All @@ -308,10 +399,9 @@ bool CInfinityNodeLockReward::ProcessBlock(int nBlockHeight, CConnman& connman)
return false;
}

// we know that nRewardHeight >= nCachedBlockHeight + Params().GetConsensus().nInfinityNodeCallLockRewardLoop
//step 0.2 we know that nRewardHeight >= nCachedBlockHeight + Params().GetConsensus().nInfinityNodeCallLockRewardLoop
int loop = (Params().GetConsensus().nInfinityNodeCallLockRewardDeepth / (nRewardHeight - nCachedBlockHeight)) - 1;
CLockRewardRequest newRequest(nRewardHeight, infRet.getBurntxOutPoint(), infRet.getSINType(), loop);
// SIGN MESSAGE TO NETWORK WITH OUR MASTERNODE KEYS
if (newRequest.Sign(infinitynodePeer.keyInfinitynode, infinitynodePeer.pubKeyInfinitynode)) {
LOCK(cs);
if (AddLockRewardRequest(newRequest)) {
Expand All @@ -323,6 +413,49 @@ bool CInfinityNodeLockReward::ProcessBlock(int nBlockHeight, CConnman& connman)
return true;
}

void CInfinityNodeLockReward::ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStream& vRecv, CConnman& connman)
{
if(fLiteMode) return; // disable all SIN specific functionality
if (strCommand == NetMsgType::INFLOCKREWARDINIT) {
CLockRewardRequest lockReq;
vRecv >> lockReq;
//dont ask pfrom for this Request anymore
uint256 nHash = lockReq.GetHash();
pfrom->setAskFor.erase(nHash);
{
LOCK(cs);
if(mapLockRewardRequest.count(nHash)) return;
if(!CheckLockRewardRequest(pfrom, lockReq, connman, nCachedBlockHeight)){
return;
}
LogPrintf("CInfinityNodeLockReward::ProcessMessage -- add new LockRewardRequest from %d\n",pfrom->GetId());
if(AddLockRewardRequest(lockReq)){
lockReq.Relay(connman);
if(!VerifyLockRewardCandidate(lockReq, connman)){
LogPrintf("CInfinityNodeLockReward::ProcessMessage -- can not send commitment. May be i am not in Top score.\n");
return;
}
}
return;
}
} else if (strCommand == NetMsgType::INFVERIFY) {
CVerifyRequest vrequest;
vRecv >> vrequest;

pfrom->setAskFor.erase(vrequest.GetHash());
{
LOCK(cs);
if(!vrequest.vchSig1.empty() && vrequest.vchSig2.empty()) {
SendVerifyReply(pfrom, vrequest, connman);
}
if(!vrequest.vchSig1.empty() && !vrequest.vchSig2.empty()) {
CheckVerifyReply(pfrom, vrequest);
}
return;
}
}
}

void CInfinityNodeLockReward::UpdatedBlockTip(const CBlockIndex *pindex, CConnman& connman)
{
if(!pindex) return;
Expand Down
11 changes: 4 additions & 7 deletions src/infinitynodelockreward.h
Expand Up @@ -180,16 +180,13 @@ class CInfinityNodeLockReward
/*TODO: Verify node at IP*/

bool SendVerifyRequest(const CAddress& addr, COutPoint myPeerBurnTx, CLockRewardRequest& lockRewardRequestRet, CConnman& connman);
/*
void SendVerifyReply(CNode* pnode, CMasternodeVerification& mnv, CConnman& connman);
void ProcessVerifyReply(CNode* pnode, CMasternodeVerification& mnv);
void ProcessVerifyBroadcast(CNode* pnode, const CMasternodeVerification& mnv);
*/
bool SendVerifyReply(CNode* pnode, CVerifyRequest& vrequest, CConnman& connman);
bool CheckVerifyReply(CNode* pnode, CVerifyRequest& vrequest);

//process consensus request message
bool getCkeyForRequest(uint256 nRequest);
bool ProcessLockRewardRequest(CNode* pfrom, CLockRewardRequest& lockRewardRequestRet, CConnman& connman, int nBlockHeight);
bool ProcessLockRewardCommitment(CLockRewardRequest& lockRewardRequestRet, CConnman& connman);
bool CheckLockRewardRequest(CNode* pfrom, CLockRewardRequest& lockRewardRequestRet, CConnman& connman, int nBlockHeight);
bool VerifyLockRewardCandidate(CLockRewardRequest& lockRewardRequestRet, CConnman& connman);
/*call in UpdatedBlockTip*/
bool ProcessBlock(int nBlockHeight, CConnman& connman);
/*call in processing.cpp when node receive INV*/
Expand Down

0 comments on commit 117a041

Please sign in to comment.