From 4d16a67c0db8429f98626856ee4cbbe39d3ecb3a Mon Sep 17 00:00:00 2001 From: Maneesha-rubix Date: Tue, 30 Apr 2024 17:20:41 +0530 Subject: [PATCH 001/129] Adding sender signature details to block --- block/block.go | 5 +++++ core/quorum_initiator.go | 32 ++++++++++++++++++++++++++++++++ did/basic.go | 2 ++ did/child.go | 2 ++ did/quorum_light.go | 2 ++ did/standard.go | 2 ++ did/wallet.go | 2 ++ 7 files changed, 47 insertions(+) diff --git a/block/block.go b/block/block.go index 19227f7e..83f89208 100644 --- a/block/block.go +++ b/block/block.go @@ -40,6 +40,7 @@ const ( TCSmartContractDataKey string = "9" TCTokenValueKey string = "10" TCChildTokensKey string = "11" + TCSenderSignatureKey string = "12" ) const ( @@ -67,6 +68,7 @@ type TokenChainBlock struct { SmartContractData string `json:"smartContractData"` TokenValue float64 `json:"tokenValue"` ChildTokens []string `json:"childTokens"` + SenderSignature string `json:"senderSignature"` } type PledgeDetail struct { @@ -151,6 +153,9 @@ func CreateNewBlock(ctcb map[string]*Block, tcb *TokenChainBlock) *Block { if tcb.SmartContractData != "" { ntcb[TCSmartContractDataKey] = tcb.SmartContractData } + if tcb.SenderSignature != "" { + ntcb[TCSenderSignatureKey] = tcb.SenderSignature + } if floatPrecisionToMaxDecimalPlaces(tcb.TokenValue) > floatPrecisionToMaxDecimalPlaces(0) { ntcb[TCTokenValueKey] = floatPrecisionToMaxDecimalPlaces(tcb.TokenValue) diff --git a/core/quorum_initiator.go b/core/quorum_initiator.go index 8bf6ccc5..ec8f3f8a 100644 --- a/core/quorum_initiator.go +++ b/core/quorum_initiator.go @@ -131,6 +131,14 @@ type CreditSignature struct { SignVersion string `json:"sign_version"` //represents sign version (PkiSign == 0 or NlssSign==1) } +type SenderSignature struct { + NLSS_share string `json:"nlss_share_signature"` + Private_sign string `json:"priv_signature"` + DID string `json:"sender_did"` + Hash string `json:"hash"` + SignVersion int `json:"sign_version"` //represents sign version (PkiSign == 0 or NlssSign==1) +} + type TokenArbitrationReq struct { Block []byte `json:"block"` } @@ -953,6 +961,29 @@ func (c *Core) pledgeQuorumToken(cr *ConensusRequest, sc *contract.Contract, tid } //tokenList = append(tokenList, cr.PartTokens...) + //Fetching sender signature to add it to transaction details + senderdid := sc.GetSenderDID() + sign_data, sender_share_sign, sender_priv_sign, err := sc.GetHashSig(senderdid) + if err != nil { + c.log.Error("failed to fetch sender sign", "err", err) + return nil, fmt.Errorf("failed to fetch sender sign") + } + sender_sign_version := dc.GetSignVersion() + sender_sign_ := &SenderSignature{ + NLSS_share: sender_share_sign, + Private_sign: sender_priv_sign, + DID: senderdid, + Hash: sign_data, + SignVersion: sender_sign_version, + } + sender_sign, err := json.Marshal(sender_sign_) + if err != nil { + c.log.Error("failed to parse sender sign", "err", err) + return nil, fmt.Errorf("failed to parse sender sign") + } + + senderSignature := string(sender_sign) + var tcb block.TokenChainBlock if cr.Mode == SmartContractDeployMode { @@ -1011,6 +1042,7 @@ func (c *Core) pledgeQuorumToken(cr *ConensusRequest, sc *contract.Contract, tid QuorumSignature: credit, SmartContract: sc.GetBlock(), PledgeDetails: ptds, + SenderSignature: senderSignature, } } diff --git a/did/basic.go b/did/basic.go index 1e4730ad..589c5a6f 100644 --- a/did/basic.go +++ b/did/basic.go @@ -63,6 +63,8 @@ func (d *DIDBasic) GetDID() string { return d.did } +// When the did creation and signing is done in Basic mode, +// this function returns the sign version as NLSSVersion = 1 func (d *DIDBasic) GetSignVersion() int { return NlssVersion } diff --git a/did/child.go b/did/child.go index 47fc7d15..342ab3d8 100644 --- a/did/child.go +++ b/did/child.go @@ -64,6 +64,8 @@ func (d *DIDChild) GetDID() string { return d.did } +// When the did creation and signing is done in Child mode, +// this function returns the sign version as NLSSVersion = 1 func (d *DIDChild) GetSignVersion() int { return NlssVersion } diff --git a/did/quorum_light.go b/did/quorum_light.go index 5926cf63..9f9f6fe0 100644 --- a/did/quorum_light.go +++ b/did/quorum_light.go @@ -49,6 +49,8 @@ func (d *DIDQuorum_Lt) GetDID() string { return d.did } +// When the did creation and signing is done in Light mode, +// this function returns the sign version as BIPVersion = 0 func (d *DIDQuorum_Lt) GetSignVersion() int { return BIPVersion } diff --git a/did/standard.go b/did/standard.go index 561a168e..a3644369 100644 --- a/did/standard.go +++ b/did/standard.go @@ -55,6 +55,8 @@ func (d *DIDStandard) GetDID() string { return d.did } +// When the did creation and signing is done in Standard mode, +// this function returns the sign version as NLSSVersion = 1 func (d *DIDStandard) GetSignVersion() int { return NlssVersion } diff --git a/did/wallet.go b/did/wallet.go index 85941bdf..8b1c423f 100644 --- a/did/wallet.go +++ b/did/wallet.go @@ -56,6 +56,8 @@ func (d *DIDWallet) GetDID() string { return d.did } +// When the did creation and signing is done in wallet mode, +// this function returns the sign version as NLSSVersion = 1 func (d *DIDWallet) GetSignVersion() int { return NlssVersion } From a3d8123f70db59a0c5f60a6350e1f9e4d078cbf0 Mon Sep 17 00:00:00 2001 From: Vaishnav CH Date: Sat, 11 May 2024 02:14:06 +0530 Subject: [PATCH 002/129] Add parts token unpledging & Fix : Pledge token sending --- core/quorum_recv.go | 29 +++++++++++++++++++++-------- core/quorum_validation.go | 6 +----- core/unpledge.go | 20 ++++++++++++++++---- core/unpledge/unpledge.go | 24 +++++++++++++++++++----- 4 files changed, 57 insertions(+), 22 deletions(-) diff --git a/core/quorum_recv.go b/core/quorum_recv.go index 284d09a6..b7e5bc9d 100644 --- a/core/quorum_recv.go +++ b/core/quorum_recv.go @@ -209,6 +209,18 @@ func (c *Core) quorumRBTConsensus(req *ensweb.Request, did string, qdc didcrypto wt := sc.GetTransTokenInfo() for i := range wt { + var tknType int + if wt[i].TokenValue == 1.0 { + tknType = token.RBTTokenType + } else { + tknType = token.PartTokenType + } + + if c.testNet && wt[i].TokenValue == 1.0 { + tknType = token.TestTokenType + } else { + tknType = token.TestPartTokenType + } b := c.w.GetLatestTokenBlock(wt[i].Token, wt[i].TokenType) if b == nil { c.log.Error("pledge token check Failed, failed to get latest block") @@ -221,7 +233,7 @@ func (c *Core) quorumRBTConsensus(req *ensweb.Request, did string, qdc didcrypto return c.l.RenderJSON(req, &crep, http.StatusOK) } if c.checkIsUnpledged(b) { - unpledgeId := c.getUnpledgeId(wt[i].Token) + unpledgeId := c.getUnpledgeId(wt[i].Token, tknType) if unpledgeId == "" { c.log.Error("Failed to fetch proof file CID") crep.Message = "Failed to fetch proof file CID" @@ -242,13 +254,13 @@ func (c *Core) quorumRBTConsensus(req *ensweb.Request, did string, qdc didcrypto pcs := util.BytesToString(pcb) senderAddr := cr.SenderPeerID + "." + sc.GetSenderDID() - rdid, tid, err := c.getProofverificationDetails(wt[i].Token, senderAddr) + rdid, tid, err := c.getProofverificationDetails(wt[i].Token, senderAddr, tknType) if err != nil { c.log.Error("Failed to get pledged for token reciveer did", "err", err) crep.Message = "Failed to get pledged for token reciveer did" return c.l.RenderJSON(req, &crep, http.StatusOK) } - pv, err := c.up.ProofVerification(wt[i].Token, pcs, rdid, tid) + pv, err := c.up.ProofVerification(wt[i].Token, pcs, rdid, tid, tknType) if err != nil { c.log.Error("Proof Verification Failed due to error ", err) crep.Message = "Proof Verification Failed due to error " + err.Error() @@ -1232,17 +1244,17 @@ func (c *Core) tokenArbitration(req *ensweb.Request) *ensweb.Result { return c.l.RenderJSON(req, &srep, http.StatusOK) } -func (c *Core) getProofverificationDetails(tokenID string, senderAddr string) (string, string, error) { +func (c *Core) getProofverificationDetails(tokenID string, senderAddr string, tknType int) (string, string, error) { var receiverDID, txnId string - tt := token.RBTTokenType - blk := c.w.GetLatestTokenBlock(tokenID, tt) + + blk := c.w.GetLatestTokenBlock(tokenID, tknType) pbid, err := blk.GetPrevBlockID(tokenID) if err != nil { c.log.Error("Failed to get the block id. Unable to verify proof file") return "", "", err } - pBlk, err := c.w.GetTokenBlock(tokenID, tt, pbid) + pBlk, err := c.w.GetTokenBlock(tokenID, tknType, pbid) if err != nil { c.log.Error("Failed to get the Previous Block Unable to verify proof file") return "", "", err @@ -1280,8 +1292,9 @@ func (c *Core) getProofverificationDetails(tokenID string, senderAddr string) (s return "", "", err } //check if token chain of token pledged for already synced to node + //TODO: Change proof verification method pledgedfBlk, err := c.w.GetTokenBlock(tokenPledgedFor, tokenPledgedForType, tokenPledgedForBlockId) - if err != nil { + if err != nil && err.Error() != "leveldb: not found" { c.log.Error("Failed to get the pledged for token's Block Unable to verify proof file") return "", "", err } diff --git a/core/quorum_validation.go b/core/quorum_validation.go index 35613821..4ed027cb 100644 --- a/core/quorum_validation.go +++ b/core/quorum_validation.go @@ -288,11 +288,7 @@ func (c *Core) validateSignature(dc did.DIDCrypto, h string, s string) bool { // return c.checkIsUnpledged(b, wt) // } -func (c *Core) getUnpledgeId(wt string) string { - tokenType := token.RBTTokenType - if c.testNet { - tokenType = token.TestTokenType - } +func (c *Core) getUnpledgeId(wt string, tokenType int) string { b := c.w.GetLatestTokenBlock(wt, tokenType) if b == nil { c.log.Error("Invalid token chain block") diff --git a/core/unpledge.go b/core/unpledge.go index 81da3d75..a4cba3d6 100644 --- a/core/unpledge.go +++ b/core/unpledge.go @@ -10,14 +10,26 @@ import ( ) func (c *Core) Unpledge(t string, file string) error { - tokenType := token.RBTTokenType - if c.testNet { + unpledgetokendetails, err := c.w.ReadToken(t) + if err != nil { + c.log.Error("Failed to fetch unpledge token details fot token ", t, " error : ", err) + } + var tokenType int + if unpledgetokendetails.TokenValue == 1.0 { + tokenType = token.RBTTokenType + } else { + tokenType = token.PartTokenType + } + + if c.testNet && unpledgetokendetails.TokenValue == 1.0 { tokenType = token.TestTokenType + } else { + tokenType = token.TestPartTokenType } b := c.w.GetLatestTokenBlock(t, tokenType) if b == nil { - c.log.Error("Failed to unpledge invalid tokne chain block") - return fmt.Errorf("Failed to unpledge invalid tokne chain block") + c.log.Error("Failed to unpledge invalid tokne chain block for token ", t, " having token type as ", tokenType) + return fmt.Errorf("Failed to unpledge invalid tokne chain block for token ", t, " having token type as ", tokenType) } f, err := os.Open(file) if err != nil { diff --git a/core/unpledge/unpledge.go b/core/unpledge/unpledge.go index f01ccb32..edaaa331 100644 --- a/core/unpledge/unpledge.go +++ b/core/unpledge/unpledge.go @@ -157,9 +157,23 @@ func (up *UnPledge) runUnpledge() { } st := time.Now() t := list.Token - tt := token.RBTTokenType - if up.testNet { + unpledgetokendetails, err := up.w.ReadToken(t) + if err != nil { + up.log.Error("Failed to fetch unpledge token details ", err) + up.s.Delete(UnpledgeQueueTable, &UnpledgeTokenList{}, "token=?", t) + continue + } + var tt int + if unpledgetokendetails.TokenValue == 1.0 { + tt = token.RBTTokenType + } else { + tt = token.PartTokenType + } + + if up.testNet && unpledgetokendetails.TokenValue == 1.0 { tt = token.TestTokenType + } else { + tt = token.TestPartTokenType } b := up.w.GetLatestTokenBlock(t, tt) if b == nil { @@ -259,9 +273,9 @@ func (up *UnPledge) runUnpledge() { } } -func (up *UnPledge) ProofVerification(tokenID string, proof []string, rdid string, tid string) (bool, error) { - tt := token.RBTTokenType - blk := up.w.GetLatestTokenBlock(tokenID, tt) +func (up *UnPledge) ProofVerification(tokenID string, proof []string, rdid string, tid string, tokenType int) (bool, error) { + + blk := up.w.GetLatestTokenBlock(tokenID, tokenType) bid, err := blk.GetPrevBlockID(tokenID) if err != nil { From 96455d357ccda4db63df363dca9eba55275ce78e Mon Sep 17 00:00:00 2001 From: Vaishnav CH Date: Tue, 14 May 2024 15:56:00 +0530 Subject: [PATCH 003/129] Change passing of tknType varible --- core/quorum_recv.go | 55 ++++++++++++++++++++++----------------------- 1 file changed, 27 insertions(+), 28 deletions(-) diff --git a/core/quorum_recv.go b/core/quorum_recv.go index b7e5bc9d..027ad72b 100644 --- a/core/quorum_recv.go +++ b/core/quorum_recv.go @@ -209,18 +209,18 @@ func (c *Core) quorumRBTConsensus(req *ensweb.Request, did string, qdc didcrypto wt := sc.GetTransTokenInfo() for i := range wt { - var tknType int - if wt[i].TokenValue == 1.0 { - tknType = token.RBTTokenType - } else { - tknType = token.PartTokenType - } - - if c.testNet && wt[i].TokenValue == 1.0 { - tknType = token.TestTokenType - } else { - tknType = token.TestPartTokenType - } + // var tknType int + // if wt[i].TokenValue == 1.0 { + // tknType = token.RBTTokenType + // } else { + // tknType = token.PartTokenType + // } + + // if c.testNet && wt[i].TokenValue == 1.0 { + // tknType = token.TestTokenType + // } else { + // tknType = token.TestPartTokenType + // } b := c.w.GetLatestTokenBlock(wt[i].Token, wt[i].TokenType) if b == nil { c.log.Error("pledge token check Failed, failed to get latest block") @@ -233,7 +233,7 @@ func (c *Core) quorumRBTConsensus(req *ensweb.Request, did string, qdc didcrypto return c.l.RenderJSON(req, &crep, http.StatusOK) } if c.checkIsUnpledged(b) { - unpledgeId := c.getUnpledgeId(wt[i].Token, tknType) + unpledgeId := c.getUnpledgeId(wt[i].Token, wt[i].TokenType) if unpledgeId == "" { c.log.Error("Failed to fetch proof file CID") crep.Message = "Failed to fetch proof file CID" @@ -254,13 +254,13 @@ func (c *Core) quorumRBTConsensus(req *ensweb.Request, did string, qdc didcrypto pcs := util.BytesToString(pcb) senderAddr := cr.SenderPeerID + "." + sc.GetSenderDID() - rdid, tid, err := c.getProofverificationDetails(wt[i].Token, senderAddr, tknType) + rdid, tid, err := c.getProofverificationDetails(wt[i].Token, senderAddr, wt[i].TokenType) if err != nil { c.log.Error("Failed to get pledged for token reciveer did", "err", err) crep.Message = "Failed to get pledged for token reciveer did" return c.l.RenderJSON(req, &crep, http.StatusOK) } - pv, err := c.up.ProofVerification(wt[i].Token, pcs, rdid, tid, tknType) + pv, err := c.up.ProofVerification(wt[i].Token, pcs, rdid, tid, wt[i].TokenType) if err != nil { c.log.Error("Proof Verification Failed due to error ", err) crep.Message = "Proof Verification Failed due to error " + err.Error() @@ -1293,19 +1293,13 @@ func (c *Core) getProofverificationDetails(tokenID string, senderAddr string, tk } //check if token chain of token pledged for already synced to node //TODO: Change proof verification method - pledgedfBlk, err := c.w.GetTokenBlock(tokenPledgedFor, tokenPledgedForType, tokenPledgedForBlockId) - if err != nil && err.Error() != "leveldb: not found" { - c.log.Error("Failed to get the pledged for token's Block Unable to verify proof file") - return "", "", err - } var pledgedforBlk *block.Block - if pledgedfBlk != nil { - pledgedforBlk = block.InitBlock(pledgedfBlk, nil) - if pledgedforBlk == nil { - c.log.Error("Failed to initialize the pledged for token's Block Unable to verify proof file") - return "", "", fmt.Errorf("Failed to initilaize previous block") - } - } else { //if token chain of token pledged for not synced fetch from sender + + pledgedfBlk, err := c.w.GetTokenBlock(tokenPledgedFor, tokenPledgedForType, tokenPledgedForBlockId) + + if err != nil { + c.log.Error("Failed to get the pledged for token's Block Unable to verify proof file, Error: " + err.Error()) + c.log.Debug("Unable get token block from storage..Proceeding for syncing...") p, err := c.getPeer(senderAddr) if err != nil { c.log.Error("Failed to get peer", "err", err) @@ -1322,8 +1316,13 @@ func (c *Core) getProofverificationDetails(tokenID string, senderAddr string, tk return "", "", err } pledgedforBlk = block.InitBlock(tcbArray, nil) + } else if pledgedfBlk != nil { + pledgedforBlk = block.InitBlock(pledgedfBlk, nil) + if pledgedforBlk == nil { + c.log.Error("Failed to initialize the pledged for token's Block Unable to verify proof file") + return "", "", fmt.Errorf("Failed to initilaize previous block") + } } - receiverDID = pledgedforBlk.GetReceiverDID() txnId = pledgedforBlk.GetTid() } From 4680091a3918353041d4e8955054ac3da2d7b0d7 Mon Sep 17 00:00:00 2001 From: Vaishnav CH Date: Tue, 14 May 2024 16:01:57 +0530 Subject: [PATCH 004/129] Change passing of tknType varible --- core/quorum_recv.go | 43 +++++++++++++++---------------------------- 1 file changed, 15 insertions(+), 28 deletions(-) diff --git a/core/quorum_recv.go b/core/quorum_recv.go index b7e5bc9d..d0c3ceb8 100644 --- a/core/quorum_recv.go +++ b/core/quorum_recv.go @@ -209,18 +209,6 @@ func (c *Core) quorumRBTConsensus(req *ensweb.Request, did string, qdc didcrypto wt := sc.GetTransTokenInfo() for i := range wt { - var tknType int - if wt[i].TokenValue == 1.0 { - tknType = token.RBTTokenType - } else { - tknType = token.PartTokenType - } - - if c.testNet && wt[i].TokenValue == 1.0 { - tknType = token.TestTokenType - } else { - tknType = token.TestPartTokenType - } b := c.w.GetLatestTokenBlock(wt[i].Token, wt[i].TokenType) if b == nil { c.log.Error("pledge token check Failed, failed to get latest block") @@ -233,7 +221,7 @@ func (c *Core) quorumRBTConsensus(req *ensweb.Request, did string, qdc didcrypto return c.l.RenderJSON(req, &crep, http.StatusOK) } if c.checkIsUnpledged(b) { - unpledgeId := c.getUnpledgeId(wt[i].Token, tknType) + unpledgeId := c.getUnpledgeId(wt[i].Token, wt[i].TokenType) if unpledgeId == "" { c.log.Error("Failed to fetch proof file CID") crep.Message = "Failed to fetch proof file CID" @@ -254,13 +242,13 @@ func (c *Core) quorumRBTConsensus(req *ensweb.Request, did string, qdc didcrypto pcs := util.BytesToString(pcb) senderAddr := cr.SenderPeerID + "." + sc.GetSenderDID() - rdid, tid, err := c.getProofverificationDetails(wt[i].Token, senderAddr, tknType) + rdid, tid, err := c.getProofverificationDetails(wt[i].Token, senderAddr, wt[i].TokenType) if err != nil { c.log.Error("Failed to get pledged for token reciveer did", "err", err) crep.Message = "Failed to get pledged for token reciveer did" return c.l.RenderJSON(req, &crep, http.StatusOK) } - pv, err := c.up.ProofVerification(wt[i].Token, pcs, rdid, tid, tknType) + pv, err := c.up.ProofVerification(wt[i].Token, pcs, rdid, tid, wt[i].TokenType) if err != nil { c.log.Error("Proof Verification Failed due to error ", err) crep.Message = "Proof Verification Failed due to error " + err.Error() @@ -1293,19 +1281,13 @@ func (c *Core) getProofverificationDetails(tokenID string, senderAddr string, tk } //check if token chain of token pledged for already synced to node //TODO: Change proof verification method - pledgedfBlk, err := c.w.GetTokenBlock(tokenPledgedFor, tokenPledgedForType, tokenPledgedForBlockId) - if err != nil && err.Error() != "leveldb: not found" { - c.log.Error("Failed to get the pledged for token's Block Unable to verify proof file") - return "", "", err - } var pledgedforBlk *block.Block - if pledgedfBlk != nil { - pledgedforBlk = block.InitBlock(pledgedfBlk, nil) - if pledgedforBlk == nil { - c.log.Error("Failed to initialize the pledged for token's Block Unable to verify proof file") - return "", "", fmt.Errorf("Failed to initilaize previous block") - } - } else { //if token chain of token pledged for not synced fetch from sender + + pledgedfBlk, err := c.w.GetTokenBlock(tokenPledgedFor, tokenPledgedForType, tokenPledgedForBlockId) + + if err != nil { + c.log.Error("Failed to get the pledged for token's Block Unable to verify proof file, Error: " + err.Error()) + c.log.Debug("Unable get token block from storage..Proceeding for syncing...") p, err := c.getPeer(senderAddr) if err != nil { c.log.Error("Failed to get peer", "err", err) @@ -1322,8 +1304,13 @@ func (c *Core) getProofverificationDetails(tokenID string, senderAddr string, tk return "", "", err } pledgedforBlk = block.InitBlock(tcbArray, nil) + } else if pledgedfBlk != nil { + pledgedforBlk = block.InitBlock(pledgedfBlk, nil) + if pledgedforBlk == nil { + c.log.Error("Failed to initialize the pledged for token's Block Unable to verify proof file") + return "", "", fmt.Errorf("Failed to initilaize previous block") + } } - receiverDID = pledgedforBlk.GetReceiverDID() txnId = pledgedforBlk.GetTid() } From 522428ee18a57a54a051aa113bb7cc1a6c133301 Mon Sep 17 00:00:00 2001 From: Vaishnav CH Date: Tue, 14 May 2024 16:29:58 +0530 Subject: [PATCH 005/129] Remove extra comments --- core/quorum_recv.go | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/core/quorum_recv.go b/core/quorum_recv.go index 027ad72b..d0c3ceb8 100644 --- a/core/quorum_recv.go +++ b/core/quorum_recv.go @@ -209,18 +209,6 @@ func (c *Core) quorumRBTConsensus(req *ensweb.Request, did string, qdc didcrypto wt := sc.GetTransTokenInfo() for i := range wt { - // var tknType int - // if wt[i].TokenValue == 1.0 { - // tknType = token.RBTTokenType - // } else { - // tknType = token.PartTokenType - // } - - // if c.testNet && wt[i].TokenValue == 1.0 { - // tknType = token.TestTokenType - // } else { - // tknType = token.TestPartTokenType - // } b := c.w.GetLatestTokenBlock(wt[i].Token, wt[i].TokenType) if b == nil { c.log.Error("pledge token check Failed, failed to get latest block") From acd7f6a7dbee5e5caa4d60d9a2911017223be0bc Mon Sep 17 00:00:00 2001 From: Allen Iype P Cherian Date: Mon, 29 Apr 2024 11:28:48 +0530 Subject: [PATCH 006/129] Add function moveFile --- server/smart_contract.go | 52 +++++++++++++++++++++++++++++++++++++--- 1 file changed, 49 insertions(+), 3 deletions(-) diff --git a/server/smart_contract.go b/server/smart_contract.go index 8f6176f6..755cb147 100644 --- a/server/smart_contract.go +++ b/server/smart_contract.go @@ -2,6 +2,7 @@ package server import ( "fmt" + "io" "os" "path/filepath" @@ -99,7 +100,7 @@ func (s *Server) APIGenerateSmartContract(req *ensweb.Request) *ensweb.Result { binaryCodeFile.Close() binaryCodeDestFile.Close() - err = os.Rename(binaryCodeFile.Name(), binaryCodeDest) + err = moveFile(binaryCodeFile.Name(), binaryCodeDest) if err != nil { binaryCodeFile.Close() s.log.Error("Generate smart contract failed, failed to move binary code file", "err", err) @@ -125,7 +126,7 @@ func (s *Server) APIGenerateSmartContract(req *ensweb.Request) *ensweb.Result { rawCodeFile.Close() rawCodeDestFile.Close() - err = os.Rename(rawCodeFile.Name(), rawCodeDest) + err = moveFile(rawCodeFile.Name(), rawCodeDest) if err != nil { binaryCodeDestFile.Close() rawCodeDestFile.Close() @@ -154,7 +155,7 @@ func (s *Server) APIGenerateSmartContract(req *ensweb.Request) *ensweb.Result { schemaFile.Close() schemaDestFile.Close() - err = os.Rename(schemaFile.Name(), schemaDest) + err = moveFile(schemaFile.Name(), schemaDest) if err != nil { binaryCodeDestFile.Close() rawCodeDestFile.Close() @@ -196,6 +197,51 @@ func (s *Server) APIGenerateSmartContract(req *ensweb.Request) *ensweb.Result { return s.BasicResponse(req, true, "Smart contract generated successfully", nil) } +// moveFile tries to rename the file first; if it fails, it falls back to copying +func moveFile(src, dst string) error { + err := os.Rename(src, dst) + if err != nil { + if linkErr, ok := err.(*os.LinkError); ok { + fmt.Println("os.Rename failed, attempting to copy:", linkErr) + + // Open the source file + sourceFile, err := os.Open(src) + if err != nil { + return fmt.Errorf("error opening source file: %w", err) + } + defer sourceFile.Close() + + // Create the destination file + destinationFile, err := os.Create(dst) + if err != nil { + return fmt.Errorf("error creating destination file: %w", err) + } + defer destinationFile.Close() + + // Copy the contents + if _, err = io.Copy(destinationFile, sourceFile); err != nil { + return fmt.Errorf("error copying file: %w", err) + } + + // Close the files explicitly before deleting + if err = sourceFile.Close(); err != nil { + return fmt.Errorf("error closing source file: %w", err) + } + if err = destinationFile.Close(); err != nil { + return fmt.Errorf("error closing destination file: %w", err) + } + + // Delete the original file + if err = os.Remove(src); err != nil { + return fmt.Errorf("error removing original file: %w", err) + } + } else { + return fmt.Errorf("os.Rename error: %w", err) + } + } + return nil +} + // SmartContract godoc // @Summary Fetch Smart Contract // @Description This API will Fetch smart contract From f6fadf771aed724447982945cd6301335cba7cd1 Mon Sep 17 00:00:00 2001 From: Allen Iype P Cherian Date: Mon, 29 Apr 2024 18:48:12 +0530 Subject: [PATCH 007/129] Add api and cmd : quorum-setup-check --- client/ping.go | 23 ++++++++++++++++++++++ command/command.go | 5 +++++ command/diagnostic.go | 2 +- command/ping.go | 12 ++++++++++++ core/core.go | 2 ++ core/ping.go | 45 +++++++++++++++++++++++++++++++++++++++++++ server/basic.go | 25 ++++++++++++++++++++++++ server/server.go | 2 ++ setup/setup.go | 1 + 9 files changed, 116 insertions(+), 1 deletion(-) diff --git a/client/ping.go b/client/ping.go index 371c1c79..5f5f7737 100644 --- a/client/ping.go +++ b/client/ping.go @@ -1,6 +1,8 @@ package client import ( + "fmt" + "strings" "time" "github.com/rubixchain/rubixgoplatform/core/model" @@ -17,3 +19,24 @@ func (c *Client) Ping(peerID string) (string, bool) { } return rm.Message, rm.Status } + +func (c *Client) CheckQuorumStatus(quorumAddress string) (string, bool) { + fmt.Println("Input address is " + quorumAddress) + q := make(map[string]string) + // Split the string into two parts based on a delimiter + parts := strings.Split(quorumAddress, ".") + if len(parts) != 2 { + // Handle the case where the string doesn't contain exactly two parts + return "Invalid quorumAddress format", false + } + // Assign the first part to "peerID" and the second part to "dID" + q["peerID"] = parts[0] + q["did"] = parts[1] + fmt.Println("Peerid " + q["peerID"] + " did is " + q["did"]) + var rm model.BasicResponse + err := c.sendJSONRequest("GET", setup.APICheckQuorumStatus, q, nil, &rm, 2*time.Minute) + if err != nil { + return "CHeck quorum failed, " + err.Error(), false + } + return rm.Message, rm.Status +} diff --git a/command/command.go b/command/command.go index 75d44e0c..1314750f 100644 --- a/command/command.go +++ b/command/command.go @@ -77,6 +77,7 @@ const ( GetTokenBlock string = "gettokenblock" GetSmartContractData string = "getsmartcontractdata" ReleaseAllLockedTokensCmd string = "releaseAllLockedTokens" + CheckQuorumStatusCmd string = "checkQuorumStatus" AddExplorerCmd string = "addexplorer" RemoveExplorerCmd string = "removeexplorer" GetAllExplorerCmd string = "getallexplorer" @@ -124,6 +125,7 @@ var commands = []string{VersionCmd, DumpSmartContractTokenChainCmd, GetTokenBlock, GetSmartContractData, + CheckQuorumStatusCmd, } var commandsHelp = []string{"To get tool version", "To get help", @@ -240,6 +242,7 @@ type Command struct { smartContractData string executorAddr string latest bool + quorumAddr string links []string mnemonicFile string ChildPath int @@ -585,6 +588,8 @@ func Run(args []string) { cmd.executeSmartcontract() case ReleaseAllLockedTokensCmd: cmd.releaseAllLockedTokens() + case CheckQuorumStatusCmd: + cmd.checkQuorumStatus() case AddExplorerCmd: cmd.addExplorer() case RemoveExplorerCmd: diff --git a/command/diagnostic.go b/command/diagnostic.go index 249fbb62..4b3fe59d 100644 --- a/command/diagnostic.go +++ b/command/diagnostic.go @@ -117,7 +117,7 @@ func tcMarshal(str string, m interface{}) (string, error) { str = str + fmt.Sprintf("%d", mt) case float64: // TokenValue (key: "10") is a float value and needs to have a precision of 5 - // in the output dump file + // in the output dump file str = str + fmt.Sprintf("%.5f", mt) case interface{}: str, err = tcMarshal(str, mt) diff --git a/command/ping.go b/command/ping.go index 71bf64b7..9da62dee 100644 --- a/command/ping.go +++ b/command/ping.go @@ -1,5 +1,7 @@ package command +import "fmt" + func (cmd *Command) ping() { msg, status := cmd.c.Ping(cmd.peerID) if !status { @@ -8,3 +10,13 @@ func (cmd *Command) ping() { cmd.log.Info("Ping response received successfully", "message", msg) } } + +func (cmd *Command) checkQuorumStatus() { + fmt.Println("checkQuorumStatus triggered") + msg, status := cmd.c.CheckQuorumStatus(cmd.quorumAddr) + if !status { + cmd.log.Error("Quorum is not setup in ", cmd.quorumAddr, " message ", msg) + } else { + cmd.log.Info("Quorum is setup in", cmd.quorumAddr, "message", msg) + } +} diff --git a/core/core.go b/core/core.go index 1990d498..0f7c1465 100644 --- a/core/core.go +++ b/core/core.go @@ -46,6 +46,7 @@ const ( APIGetTokenNumber string = "/api/get-token-number" APIGetMigratedTokenStatus string = "/api/get-Migrated-token-status" APISyncDIDArbitration string = "/api/sync-did-arbitration" + APICheckQuorumStatus string = "/api/check-quorum-status" ) const ( @@ -318,6 +319,7 @@ func (c *Core) SetupCore() error { } c.w.SetupWallet(c.ipfs) c.PingSetup() + //!TODO c.checkQuorumStatus c.peerSetup() c.w.AddDIDLastChar() c.SetupToken() diff --git a/core/ping.go b/core/ping.go index b8ac405a..bbc8686c 100644 --- a/core/ping.go +++ b/core/ping.go @@ -1,6 +1,7 @@ package core import ( + "fmt" "net/http" "time" @@ -51,3 +52,47 @@ func (c *Core) PingPeer(peerID string) (string, error) { } return pingResp.Message, nil } + +// CheckQuorumStatusResponse is the handler for CheckQuorumStatus request +func (c *Core) CheckQuorumStatusResponse(req *ensweb.Request) *ensweb.Result { //PingRecevied + did := c.l.GetQuerry(req, "did") + c.log.Info("Checking Quorum Status") + resp := &PingResponse{ + BasicResponse: model.BasicResponse{ + Status: false, + }, + } + _, ok := c.qc[did] + if !ok { + c.log.Error("Quorum is not setup") + resp.Message = "Quorum is not setup" + return c.l.RenderJSON(req, &resp, http.StatusOK) + } else { + resp.Status = true + resp.Message = "Quorum is setup" + return c.l.RenderJSON(req, &resp, http.StatusOK) + } + +} + +// CheckQuorumStatus will ping the peer & get the response +func (c *Core) CheckQuorumStatus(peerID string, did string) (string, error) { // + fmt.Println("peer id is " + peerID + " did is " + did) + p, err := c.pm.OpenPeerConn(peerID, "", c.getCoreAppName(peerID)) + if err != nil { + return "", err + } + // Close the p2p before exit + defer p.Close() + var checkQuorumStatusResponse PingResponse + err = p.SendJSONRequest("GET", APICheckQuorumStatus, nil, nil, &checkQuorumStatusResponse, false, 2*time.Minute) + if err != nil { + return "", err + } + return checkQuorumStatusResponse.Message, nil +} + +// PingSetup will setup the ping route +func (c *Core) CheckQuorumStatusSetup() { + c.l.AddRoute(APICheckQuorumStatus, "GET", c.CheckQuorumStatusResponse) +} diff --git a/server/basic.go b/server/basic.go index b6c29d98..3d5da7ee 100644 --- a/server/basic.go +++ b/server/basic.go @@ -1,7 +1,9 @@ package server import ( + "fmt" "net/http" + "strings" "time" "github.com/rubixchain/rubixgoplatform/core/model" @@ -63,3 +65,26 @@ func (s *Server) APIPing(req *ensweb.Request) *ensweb.Result { } return s.BasicResponse(req, true, str, nil) } + +// APIPing will ping to given peer +func (s *Server) APICheckQuorumStatus(req *ensweb.Request) *ensweb.Result { + fmt.Println("APICheckQuorumStatus in basic.go") + qAddress := s.GetQuerry(req, "quorumAddress") + // Split the string into two parts based on a delimiter + parts := strings.Split(qAddress, ".") + if len(parts) != 2 { + // Handle the case where the string doesn't contain exactly two parts + fmt.Println("Invalid quorumAddress format") + } + // Assign the first part to "peerID" and the second part to "dID" + peerID := parts[0] + dID := parts[1] + + fmt.Println("peerid in basic " + peerID + " did is " + dID) + str, err := s.c.CheckQuorumStatus(peerID, dID) + if err != nil { + s.log.Error("Quorum status check failed", "err", err) + return s.BasicResponse(req, false, str, nil) + } + return s.BasicResponse(req, true, str, nil) +} diff --git a/server/server.go b/server/server.go index a06054b0..e831a91b 100644 --- a/server/server.go +++ b/server/server.go @@ -155,6 +155,8 @@ func (s *Server) RegisterRoutes() { s.AddRoute(setup.APIGetTxnByNode, "GET", s.AuthHandle(s.APIGetTxnByNode, true, s.AuthError, false)) s.AddRoute(setup.APIRemoveTokenChainBlock, "POST", s.AuthHandle(s.APIRemoveTokenChainBlock, true, s.AuthError, false)) s.AddRoute(setup.APIReleaseAllLockedTokens, "GET", s.AuthHandle(s.APIReleaseAllLockedTokens, true, s.AuthError, false)) + s.AddRoute(setup.APICheckQuorumStatus, "GET", s.AuthHandle(s.APICheckQuorumStatus, false, s.AuthError, false)) + s.AddRoute(setup.APIGetAllExplorer, "GET", s.AuthHandle(s.APIGetAllExplorer, false, s.AuthError, true)) s.AddRoute(setup.APIAddExplorer, "POST", s.AuthHandle(s.APIAddExplorer, false, s.AuthError, true)) s.AddRoute(setup.APIRemoveExplorer, "POST", s.AuthHandle(s.APIRemoveExplorer, false, s.AuthError, true)) diff --git a/setup/setup.go b/setup/setup.go index bd7e417a..27fe74df 100644 --- a/setup/setup.go +++ b/setup/setup.go @@ -62,6 +62,7 @@ const ( APIGetTxnByNode string = "/api/get-by-node" APIRemoveTokenChainBlock string = "/api/remove-token-chain-block" APIReleaseAllLockedTokens string = "/api/release-all-locked-tokens" + APICheckQuorumStatus string = "/api/check-quorum-status" APIGetAllExplorer string = "/api/get-all-explorer" APIAddExplorer string = "/api/add-explorer" APIRemoveExplorer string = "/api/remove-explorer" From 5031ea389c2cc0cba0d1ea686b478dbb28b9054d Mon Sep 17 00:00:00 2001 From: Allen Iype P Cherian Date: Tue, 30 Apr 2024 14:23:46 +0530 Subject: [PATCH 008/129] Fix: flag quorumAddr not found [Add debug : WIP-Breaking] --- client/ping.go | 7 ++++--- command/command.go | 1 + core/ipfsport/peer.go | 3 +++ core/ping.go | 6 ++++-- server/basic.go | 1 + 5 files changed, 13 insertions(+), 5 deletions(-) diff --git a/client/ping.go b/client/ping.go index 5f5f7737..c60f076b 100644 --- a/client/ping.go +++ b/client/ping.go @@ -30,9 +30,10 @@ func (c *Client) CheckQuorumStatus(quorumAddress string) (string, bool) { return "Invalid quorumAddress format", false } // Assign the first part to "peerID" and the second part to "dID" - q["peerID"] = parts[0] - q["did"] = parts[1] - fmt.Println("Peerid " + q["peerID"] + " did is " + q["did"]) + // q["peerID"] = parts[0] + // q["did"] = parts[1] + // fmt.Println("Peerid " + q["peerID"] + " did is " + q["did"]) + q["quorumAddress"] = quorumAddress var rm model.BasicResponse err := c.sendJSONRequest("GET", setup.APICheckQuorumStatus, q, nil, &rm, 2*time.Minute) if err != nil { diff --git a/command/command.go b/command/command.go index 1314750f..85dd115a 100644 --- a/command/command.go +++ b/command/command.go @@ -440,6 +440,7 @@ func Run(args []string) { flag.StringVar(&cmd.smartContractData, "sctData", "data", "Smart contract execution info") flag.StringVar(&cmd.executorAddr, "executorAddr", "", "Smart contract Executor Address") flag.BoolVar(&cmd.latest, "latest", false, "flag to set latest") + flag.StringVar(&cmd.quorumAddr, "quorumAddr", "", "Quorum Node Address to check the status of the Quorum") flag.StringVar(&links, "links", "", "Explorer url") if len(os.Args) < 2 { diff --git a/core/ipfsport/peer.go b/core/ipfsport/peer.go index b5837baa..d4533747 100644 --- a/core/ipfsport/peer.go +++ b/core/ipfsport/peer.go @@ -132,6 +132,9 @@ func (pm *PeerManager) SwarmConnect(peerID string) bool { } func (pm *PeerManager) OpenPeerConn(peerID string, did string, appname string) (*Peer, error) { + fmt.Println("Peer ID in OpenPeerConn", peerID) + fmt.Println("DID in OpenPeerConn", did) + fmt.Println("Appname in OpenPeerConn", appname) // local peer if peerID == pm.peerID { var err error diff --git a/core/ping.go b/core/ping.go index bbc8686c..2ba531fb 100644 --- a/core/ping.go +++ b/core/ping.go @@ -80,14 +80,16 @@ func (c *Core) CheckQuorumStatus(peerID string, did string) (string, error) { // fmt.Println("peer id is " + peerID + " did is " + did) p, err := c.pm.OpenPeerConn(peerID, "", c.getCoreAppName(peerID)) if err != nil { - return "", err + fmt.Println("Error in Open Peer Conn", err) + return "Open Peer Connection Error", err } // Close the p2p before exit defer p.Close() var checkQuorumStatusResponse PingResponse err = p.SendJSONRequest("GET", APICheckQuorumStatus, nil, nil, &checkQuorumStatusResponse, false, 2*time.Minute) if err != nil { - return "", err + fmt.Println("Error in sending Json Request ", err) + return "Send Json Request error ", err } return checkQuorumStatusResponse.Message, nil } diff --git a/server/basic.go b/server/basic.go index 3d5da7ee..eb0dd749 100644 --- a/server/basic.go +++ b/server/basic.go @@ -70,6 +70,7 @@ func (s *Server) APIPing(req *ensweb.Request) *ensweb.Result { func (s *Server) APICheckQuorumStatus(req *ensweb.Request) *ensweb.Result { fmt.Println("APICheckQuorumStatus in basic.go") qAddress := s.GetQuerry(req, "quorumAddress") + fmt.Println("QuorumAddress", qAddress) // Split the string into two parts based on a delimiter parts := strings.Split(qAddress, ".") if len(parts) != 2 { From a3c18d4c91cff68079371ea9a0e18f4f67f1b1b3 Mon Sep 17 00:00:00 2001 From: Allen Iype P Cherian Date: Tue, 30 Apr 2024 16:20:51 +0530 Subject: [PATCH 009/129] Fix: Quorom Status Check [Working] --- client/ping.go | 4 +++- command/ping.go | 13 +++++++++---- core/core.go | 4 ++-- core/ping.go | 19 ++++++++++++------- core/quorum_recv.go | 1 + server/basic.go | 4 ++++ 6 files changed, 31 insertions(+), 14 deletions(-) diff --git a/client/ping.go b/client/ping.go index c60f076b..015efdbc 100644 --- a/client/ping.go +++ b/client/ping.go @@ -37,7 +37,9 @@ func (c *Client) CheckQuorumStatus(quorumAddress string) (string, bool) { var rm model.BasicResponse err := c.sendJSONRequest("GET", setup.APICheckQuorumStatus, q, nil, &rm, 2*time.Minute) if err != nil { - return "CHeck quorum failed, " + err.Error(), false + return "Check quorum failed, " + err.Error(), false } + fmt.Println("client ping response is ", rm) + fmt.Println("status in client ", rm.Status) return rm.Message, rm.Status } diff --git a/command/ping.go b/command/ping.go index 9da62dee..09873952 100644 --- a/command/ping.go +++ b/command/ping.go @@ -1,6 +1,9 @@ package command -import "fmt" +import ( + "fmt" + "strings" +) func (cmd *Command) ping() { msg, status := cmd.c.Ping(cmd.peerID) @@ -14,9 +17,11 @@ func (cmd *Command) ping() { func (cmd *Command) checkQuorumStatus() { fmt.Println("checkQuorumStatus triggered") msg, status := cmd.c.CheckQuorumStatus(cmd.quorumAddr) - if !status { - cmd.log.Error("Quorum is not setup in ", cmd.quorumAddr, " message ", msg) - } else { + fmt.Println("cmd msg is ", msg) + fmt.Println("cmd status is ", status) + if strings.Contains(msg, "Quorum is setup") { cmd.log.Info("Quorum is setup in", cmd.quorumAddr, "message", msg) + } else { + cmd.log.Error("Quorum is not setup in ", cmd.quorumAddr, " message ", msg) } } diff --git a/core/core.go b/core/core.go index 0f7c1465..8ceeff82 100644 --- a/core/core.go +++ b/core/core.go @@ -46,7 +46,7 @@ const ( APIGetTokenNumber string = "/api/get-token-number" APIGetMigratedTokenStatus string = "/api/get-Migrated-token-status" APISyncDIDArbitration string = "/api/sync-did-arbitration" - APICheckQuorumStatus string = "/api/check-quorum-status" + APICheckQuorumStatusPath string = "/api/check-quorum-status" ) const ( @@ -319,7 +319,7 @@ func (c *Core) SetupCore() error { } c.w.SetupWallet(c.ipfs) c.PingSetup() - //!TODO c.checkQuorumStatus + c.CheckQuorumStatusSetup() c.peerSetup() c.w.AddDIDLastChar() c.SetupToken() diff --git a/core/ping.go b/core/ping.go index 2ba531fb..4281b0ba 100644 --- a/core/ping.go +++ b/core/ping.go @@ -24,6 +24,11 @@ func (c *Core) PingSetup() { c.l.AddRoute(APIPingPath, "GET", c.PingRecevied) } +// CheckQuorumStatusSetup will setup the ping route +func (c *Core) CheckQuorumStatusSetup() { + c.l.AddRoute(APICheckQuorumStatusPath, "GET", c.CheckQuorumStatusResponse) +} + // PingRecevied is the handler for ping request func (c *Core) PingRecevied(req *ensweb.Request) *ensweb.Result { c.log.Info("Ping Received") @@ -62,10 +67,12 @@ func (c *Core) CheckQuorumStatusResponse(req *ensweb.Request) *ensweb.Result { / Status: false, }, } + fmt.Println("Inout did is ", did) _, ok := c.qc[did] if !ok { - c.log.Error("Quorum is not setup") + c.log.Error("Quorum is not setup in core ping.go") resp.Message = "Quorum is not setup" + resp.Status = false return c.l.RenderJSON(req, &resp, http.StatusOK) } else { resp.Status = true @@ -77,6 +84,7 @@ func (c *Core) CheckQuorumStatusResponse(req *ensweb.Request) *ensweb.Result { / // CheckQuorumStatus will ping the peer & get the response func (c *Core) CheckQuorumStatus(peerID string, did string) (string, error) { // + q := make(map[string]string) fmt.Println("peer id is " + peerID + " did is " + did) p, err := c.pm.OpenPeerConn(peerID, "", c.getCoreAppName(peerID)) if err != nil { @@ -85,16 +93,13 @@ func (c *Core) CheckQuorumStatus(peerID string, did string) (string, error) { // } // Close the p2p before exit defer p.Close() + q["did"] = did var checkQuorumStatusResponse PingResponse - err = p.SendJSONRequest("GET", APICheckQuorumStatus, nil, nil, &checkQuorumStatusResponse, false, 2*time.Minute) + err = p.SendJSONRequest("GET", APICheckQuorumStatusPath, q, nil, &checkQuorumStatusResponse, false, 2*time.Minute) if err != nil { fmt.Println("Error in sending Json Request ", err) return "Send Json Request error ", err } + fmt.Println("core ping checkQuorumStatusResponse ", checkQuorumStatusResponse) return checkQuorumStatusResponse.Message, nil } - -// PingSetup will setup the ping route -func (c *Core) CheckQuorumStatusSetup() { - c.l.AddRoute(APICheckQuorumStatus, "GET", c.CheckQuorumStatusResponse) -} diff --git a/core/quorum_recv.go b/core/quorum_recv.go index f9a6f607..c0523491 100644 --- a/core/quorum_recv.go +++ b/core/quorum_recv.go @@ -529,6 +529,7 @@ func (c *Core) quorumConensus(req *ensweb.Request) *ensweb.Result { return c.l.RenderJSON(req, &crep, http.StatusOK) } qdc, ok := c.qc[did] + fmt.Println("qdc in quorumreceiver core is ", qdc) if !ok { c.log.Error("Quorum is not setup") crep.Message = "Quorum is not setup" diff --git a/server/basic.go b/server/basic.go index eb0dd749..670c2c6e 100644 --- a/server/basic.go +++ b/server/basic.go @@ -76,6 +76,7 @@ func (s *Server) APICheckQuorumStatus(req *ensweb.Request) *ensweb.Result { if len(parts) != 2 { // Handle the case where the string doesn't contain exactly two parts fmt.Println("Invalid quorumAddress format") + return s.BasicResponse(req, false, "Invalid Quorum Address Format", nil) } // Assign the first part to "peerID" and the second part to "dID" peerID := parts[0] @@ -83,6 +84,9 @@ func (s *Server) APICheckQuorumStatus(req *ensweb.Request) *ensweb.Result { fmt.Println("peerid in basic " + peerID + " did is " + dID) str, err := s.c.CheckQuorumStatus(peerID, dID) + if strings.Contains(str, "") { + fmt.Println("str in server basic is ", str) + } if err != nil { s.log.Error("Quorum status check failed", "err", err) return s.BasicResponse(req, false, str, nil) From b24fa9c40ae6b769bcc23cc30bb79b96e7c3370e Mon Sep 17 00:00:00 2001 From: Allen Iype P Cherian Date: Tue, 30 Apr 2024 18:43:42 +0530 Subject: [PATCH 010/129] Update quorumlist to support Alternate quorum --- core/diagnostic.go | 56 ++++++++++++++++++++++++++++++++++++++++ core/ping.go | 8 +++--- core/quorum_initiator.go | 16 +++++++++++- server/basic.go | 11 ++++---- 4 files changed, 81 insertions(+), 10 deletions(-) diff --git a/core/diagnostic.go b/core/diagnostic.go index 9a44c2d3..d7a216a0 100644 --- a/core/diagnostic.go +++ b/core/diagnostic.go @@ -1,6 +1,8 @@ package core import ( + "fmt" + "strings" "time" "github.com/rubixchain/rubixgoplatform/block" @@ -205,3 +207,57 @@ func (c *Core) ReleaseAllLockedTokens() model.BasicResponse { response.Message = "All Locked Tokens Releases Successfully Or NO Locked Tokens to release" return *response } + +func (c *Core) GetFinalQuorumList(ql []string) []string { + // Initialize finalQl as an empty slice to store the groups that meet the condition + fmt.Println("input ql is ", ql) + var finalQl []string + + // Loop through ql in groups of 5 items + for i := 0; i < len(ql); i += 5 { + end := i + 5 + if end > len(ql) { + end = len(ql) + } + group := ql[i:end] + + // Initialize a variable to keep track of whether all items in the group meet the condition + allQuorumSetup := true + + // Loop through the items in the group and check if their response message is "quorum is setup" + for _, item := range group { + parts := strings.Split(item, ".") + if len(parts) != 2 { + fmt.Println("Invalid value format at index of ql:", item) + continue + } + peerID := parts[0] + did := parts[1] + fmt.Println("checking quorum sttus for ", peerID, " . ", did) + msg, _, err := c.CheckQuorumStatus(peerID, did) + if err != nil { + fmt.Println("Failed to check quorum status:", err) + continue + } + fmt.Println("Message: ", msg, "from quorum ", peerID, ".", did) + if msg != "Quorum is setup" { + // If any item in the group does not have the response message as "quorum is setup", + // set allQuorumSetup to false and break the loop + allQuorumSetup = false + break + } + } + + // If all items in the group have the response message as "quorum is setup", + // append the group to finalQl + if allQuorumSetup { + finalQl = append(finalQl, group...) + break + } + } + + fmt.Println("Final QL: ", finalQl) + + // Return finalQl + return finalQl +} diff --git a/core/ping.go b/core/ping.go index 4281b0ba..6fe7d679 100644 --- a/core/ping.go +++ b/core/ping.go @@ -83,13 +83,13 @@ func (c *Core) CheckQuorumStatusResponse(req *ensweb.Request) *ensweb.Result { / } // CheckQuorumStatus will ping the peer & get the response -func (c *Core) CheckQuorumStatus(peerID string, did string) (string, error) { // +func (c *Core) CheckQuorumStatus(peerID string, did string) (string, bool, error) { // q := make(map[string]string) fmt.Println("peer id is " + peerID + " did is " + did) p, err := c.pm.OpenPeerConn(peerID, "", c.getCoreAppName(peerID)) if err != nil { fmt.Println("Error in Open Peer Conn", err) - return "Open Peer Connection Error", err + return "Open Peer Connection Error", false, err } // Close the p2p before exit defer p.Close() @@ -98,8 +98,8 @@ func (c *Core) CheckQuorumStatus(peerID string, did string) (string, error) { // err = p.SendJSONRequest("GET", APICheckQuorumStatusPath, q, nil, &checkQuorumStatusResponse, false, 2*time.Minute) if err != nil { fmt.Println("Error in sending Json Request ", err) - return "Send Json Request error ", err + return "Send Json Request error ", false, err } fmt.Println("core ping checkQuorumStatusResponse ", checkQuorumStatusResponse) - return checkQuorumStatusResponse.Message, nil + return checkQuorumStatusResponse.Message, checkQuorumStatusResponse.Status, nil } diff --git a/core/quorum_initiator.go b/core/quorum_initiator.go index ec8f3f8a..9e40a522 100644 --- a/core/quorum_initiator.go +++ b/core/quorum_initiator.go @@ -318,11 +318,23 @@ func (c *Core) initiateConsensus(cr *ConensusRequest, sc *contract.Contract, dc c.log.Error("Failed to get required quorums") return nil, nil, fmt.Errorf("failed to get required quorums") } + var finalQl []string + if cr.Type == 2 { + fmt.Println("quorum list with cr type 2 :") + fmt.Println(ql) + finalQl = c.GetFinalQuorumList(ql) + fmt.Println("Final groups with all quorums setup:", finalQl) + } + c.qlock.Lock() c.quorumRequest[cr.ReqID] = &cs c.pd[cr.ReqID] = &pd c.qlock.Unlock() - cr.QuorumList = ql + if len(finalQl) != 5 { + cr.QuorumList = finalQl + c.log.Error("Insufficent quromlist set") + } + //cr.QuorumList=ql defer func() { c.qlock.Lock() delete(c.quorumRequest, cr.ReqID) @@ -330,6 +342,8 @@ func (c *Core) initiateConsensus(cr *ConensusRequest, sc *contract.Contract, dc c.qlock.Unlock() }() + fmt.Println("quorum list is ", ql, " length of ql is ", len(ql)) + for _, a := range ql { //This part of code is trying to connect to the quorums in quorum list, where various functions are called to pledge the tokens //and checking of transaction by the quorum i.e. consensus for the transaction. Once the quorum is connected, it pledges and diff --git a/server/basic.go b/server/basic.go index 670c2c6e..f799cb83 100644 --- a/server/basic.go +++ b/server/basic.go @@ -83,13 +83,14 @@ func (s *Server) APICheckQuorumStatus(req *ensweb.Request) *ensweb.Result { dID := parts[1] fmt.Println("peerid in basic " + peerID + " did is " + dID) - str, err := s.c.CheckQuorumStatus(peerID, dID) - if strings.Contains(str, "") { - fmt.Println("str in server basic is ", str) - } + str, status, err := s.c.CheckQuorumStatus(peerID, dID) if err != nil { s.log.Error("Quorum status check failed", "err", err) return s.BasicResponse(req, false, str, nil) } - return s.BasicResponse(req, true, str, nil) + /* if !status { + s.log.Error("Quorum setup is not done") + return s.BasicResponse(req, status, str, nil) + } */ + return s.BasicResponse(req, status, str, nil) } From 17da864904e1e04bc9255e5e47d3e8e11456bd8b Mon Sep 17 00:00:00 2001 From: Allen Iype P Cherian Date: Wed, 1 May 2024 01:33:55 +0530 Subject: [PATCH 011/129] Fix : Consensus request to selected quorums only- Alternate Quorums --- command/command.go | 2 +- core/quorum_initiator.go | 11 +++++------ core/quorum_recv.go | 2 ++ core/quorum_validation.go | 6 ++++++ 4 files changed, 14 insertions(+), 7 deletions(-) diff --git a/command/command.go b/command/command.go index 85dd115a..4f5a143f 100644 --- a/command/command.go +++ b/command/command.go @@ -33,7 +33,7 @@ const ( ) const ( - version string = "0.0.15" + version string = "0.0.16b" ) const ( VersionCmd string = "-v" diff --git a/core/quorum_initiator.go b/core/quorum_initiator.go index 9e40a522..69c51dda 100644 --- a/core/quorum_initiator.go +++ b/core/quorum_initiator.go @@ -323,18 +323,16 @@ func (c *Core) initiateConsensus(cr *ConensusRequest, sc *contract.Contract, dc fmt.Println("quorum list with cr type 2 :") fmt.Println(ql) finalQl = c.GetFinalQuorumList(ql) + cr.QuorumList = finalQl fmt.Println("Final groups with all quorums setup:", finalQl) + } else { + cr.QuorumList = ql } c.qlock.Lock() c.quorumRequest[cr.ReqID] = &cs c.pd[cr.ReqID] = &pd c.qlock.Unlock() - if len(finalQl) != 5 { - cr.QuorumList = finalQl - c.log.Error("Insufficent quromlist set") - } - //cr.QuorumList=ql defer func() { c.qlock.Lock() delete(c.quorumRequest, cr.ReqID) @@ -344,7 +342,7 @@ func (c *Core) initiateConsensus(cr *ConensusRequest, sc *contract.Contract, dc fmt.Println("quorum list is ", ql, " length of ql is ", len(ql)) - for _, a := range ql { + for _, a := range cr.QuorumList { //This part of code is trying to connect to the quorums in quorum list, where various functions are called to pledge the tokens //and checking of transaction by the quorum i.e. consensus for the transaction. Once the quorum is connected, it pledges and //checks the consensus. For type 1 quorums, along with connecting to the quorums, we are checking the balance of the quorum DID @@ -767,6 +765,7 @@ func (c *Core) connectQuorum(cr *ConensusRequest, addr string, qt int, sc *contr var p *ipfsport.Peer var err error p, err = c.getPeer(addr) + fmt.Println("QuorumList in connect Quorum", cr.QuorumList) if err != nil { c.log.Error("Failed to get peer connection", "err", err) c.finishConsensus(cr.ReqID, qt, nil, false, "", nil, nil) diff --git a/core/quorum_recv.go b/core/quorum_recv.go index c0523491..dd87f4a3 100644 --- a/core/quorum_recv.go +++ b/core/quorum_recv.go @@ -175,6 +175,7 @@ func (c *Core) quorumRBTConsensus(req *ensweb.Request, did string, qdc didcrypto tokenStateCheckResult := make([]TokenStateCheckResult, len(ti)) c.log.Debug("entering validation to check if token state is exhausted, ti len", len(ti)) + fmt.Println("Cr.QuorumList =", cr.QuorumList) for i := range ti { wg.Add(1) go c.checkTokenState(ti[i].Token, did, i, tokenStateCheckResult, &wg, cr.QuorumList, ti[i].TokenType) @@ -538,6 +539,7 @@ func (c *Core) quorumConensus(req *ensweb.Request) *ensweb.Result { switch cr.Mode { case RBTTransferMode: c.log.Debug("RBT consensus started") + fmt.Println("Cr.Quorumlist insie case RBTTransferMode =", cr.QuorumList) return c.quorumRBTConsensus(req, did, qdc, &cr) case DTCommitMode: c.log.Debug("Data consensus started") diff --git a/core/quorum_validation.go b/core/quorum_validation.go index 5865618f..44ed9c1d 100644 --- a/core/quorum_validation.go +++ b/core/quorum_validation.go @@ -360,6 +360,7 @@ func (c *Core) checkTokenState(tokenId, did string, index int, resultArray []Tok //check dht to see if any pin exist list, err1 := c.GetDHTddrs(tokenIDTokenStateHash) + fmt.Println("List in checkToken State", list) //try to call ipfs cat to check if any one has pinned the state i.e \ if err1 != nil { c.log.Error("Error fetching content for the tokenstate ipfs hash :", tokenIDTokenStateHash, "Error", err) @@ -383,7 +384,11 @@ func (c *Core) checkTokenState(tokenId, did string, index int, resultArray []Tok } qPeerIds = append(qPeerIds, pId) } + fmt.Println("QpeerIds in checkTokenState", qPeerIds) + updatedList := c.removeStrings(list, qPeerIds) + fmt.Println("Updated List in checkToken state", updatedList) + //if pin exist abort if len(updatedList) != 0 { c.log.Debug("Token state is exhausted, Token is being Double spent. Token : ", tokenId) @@ -393,6 +398,7 @@ func (c *Core) checkTokenState(tokenId, did string, index int, resultArray []Tok resultArray[index] = result return } + c.log.Debug("Token state is not exhausted, Unique Txn") result.Error = nil result.Message = "Token state is free, Unique Txn" From 5d9a84e0c5f0472d1671be596bae1023ff8e8b88 Mon Sep 17 00:00:00 2001 From: Allen Iype P Cherian Date: Wed, 1 May 2024 01:55:28 +0530 Subject: [PATCH 012/129] Fix : Consensus request to selected quorums only- Alternate Quorums W/O comment --- client/ping.go | 8 -------- command/ping.go | 7 ++----- core/diagnostic.go | 10 +--------- core/ipfsport/peer.go | 3 --- core/ping.go | 6 ------ core/quorum.go | 5 ----- core/quorum_initiator.go | 9 +-------- core/quorum_recv.go | 3 --- core/quorum_validation.go | 8 ++------ core/smart_contract.go | 2 +- server/basic.go | 12 ++---------- 11 files changed, 9 insertions(+), 64 deletions(-) diff --git a/client/ping.go b/client/ping.go index 015efdbc..3b613d57 100644 --- a/client/ping.go +++ b/client/ping.go @@ -1,7 +1,6 @@ package client import ( - "fmt" "strings" "time" @@ -21,7 +20,6 @@ func (c *Client) Ping(peerID string) (string, bool) { } func (c *Client) CheckQuorumStatus(quorumAddress string) (string, bool) { - fmt.Println("Input address is " + quorumAddress) q := make(map[string]string) // Split the string into two parts based on a delimiter parts := strings.Split(quorumAddress, ".") @@ -29,17 +27,11 @@ func (c *Client) CheckQuorumStatus(quorumAddress string) (string, bool) { // Handle the case where the string doesn't contain exactly two parts return "Invalid quorumAddress format", false } - // Assign the first part to "peerID" and the second part to "dID" - // q["peerID"] = parts[0] - // q["did"] = parts[1] - // fmt.Println("Peerid " + q["peerID"] + " did is " + q["did"]) q["quorumAddress"] = quorumAddress var rm model.BasicResponse err := c.sendJSONRequest("GET", setup.APICheckQuorumStatus, q, nil, &rm, 2*time.Minute) if err != nil { return "Check quorum failed, " + err.Error(), false } - fmt.Println("client ping response is ", rm) - fmt.Println("status in client ", rm.Status) return rm.Message, rm.Status } diff --git a/command/ping.go b/command/ping.go index 09873952..5623ec62 100644 --- a/command/ping.go +++ b/command/ping.go @@ -1,7 +1,6 @@ package command import ( - "fmt" "strings" ) @@ -15,10 +14,8 @@ func (cmd *Command) ping() { } func (cmd *Command) checkQuorumStatus() { - fmt.Println("checkQuorumStatus triggered") - msg, status := cmd.c.CheckQuorumStatus(cmd.quorumAddr) - fmt.Println("cmd msg is ", msg) - fmt.Println("cmd status is ", status) + msg, _ := cmd.c.CheckQuorumStatus(cmd.quorumAddr) + //Verification with "status" pending ! if strings.Contains(msg, "Quorum is setup") { cmd.log.Info("Quorum is setup in", cmd.quorumAddr, "message", msg) } else { diff --git a/core/diagnostic.go b/core/diagnostic.go index d7a216a0..7d555750 100644 --- a/core/diagnostic.go +++ b/core/diagnostic.go @@ -1,7 +1,6 @@ package core import ( - "fmt" "strings" "time" @@ -210,7 +209,6 @@ func (c *Core) ReleaseAllLockedTokens() model.BasicResponse { func (c *Core) GetFinalQuorumList(ql []string) []string { // Initialize finalQl as an empty slice to store the groups that meet the condition - fmt.Println("input ql is ", ql) var finalQl []string // Loop through ql in groups of 5 items @@ -228,18 +226,15 @@ func (c *Core) GetFinalQuorumList(ql []string) []string { for _, item := range group { parts := strings.Split(item, ".") if len(parts) != 2 { - fmt.Println("Invalid value format at index of ql:", item) continue } peerID := parts[0] did := parts[1] - fmt.Println("checking quorum sttus for ", peerID, " . ", did) msg, _, err := c.CheckQuorumStatus(peerID, did) if err != nil { - fmt.Println("Failed to check quorum status:", err) + c.log.Error("Failed to check quorum status:", err) continue } - fmt.Println("Message: ", msg, "from quorum ", peerID, ".", did) if msg != "Quorum is setup" { // If any item in the group does not have the response message as "quorum is setup", // set allQuorumSetup to false and break the loop @@ -255,9 +250,6 @@ func (c *Core) GetFinalQuorumList(ql []string) []string { break } } - - fmt.Println("Final QL: ", finalQl) - // Return finalQl return finalQl } diff --git a/core/ipfsport/peer.go b/core/ipfsport/peer.go index d4533747..b5837baa 100644 --- a/core/ipfsport/peer.go +++ b/core/ipfsport/peer.go @@ -132,9 +132,6 @@ func (pm *PeerManager) SwarmConnect(peerID string) bool { } func (pm *PeerManager) OpenPeerConn(peerID string, did string, appname string) (*Peer, error) { - fmt.Println("Peer ID in OpenPeerConn", peerID) - fmt.Println("DID in OpenPeerConn", did) - fmt.Println("Appname in OpenPeerConn", appname) // local peer if peerID == pm.peerID { var err error diff --git a/core/ping.go b/core/ping.go index 6fe7d679..ea8d37e7 100644 --- a/core/ping.go +++ b/core/ping.go @@ -1,7 +1,6 @@ package core import ( - "fmt" "net/http" "time" @@ -67,7 +66,6 @@ func (c *Core) CheckQuorumStatusResponse(req *ensweb.Request) *ensweb.Result { / Status: false, }, } - fmt.Println("Inout did is ", did) _, ok := c.qc[did] if !ok { c.log.Error("Quorum is not setup in core ping.go") @@ -85,10 +83,8 @@ func (c *Core) CheckQuorumStatusResponse(req *ensweb.Request) *ensweb.Result { / // CheckQuorumStatus will ping the peer & get the response func (c *Core) CheckQuorumStatus(peerID string, did string) (string, bool, error) { // q := make(map[string]string) - fmt.Println("peer id is " + peerID + " did is " + did) p, err := c.pm.OpenPeerConn(peerID, "", c.getCoreAppName(peerID)) if err != nil { - fmt.Println("Error in Open Peer Conn", err) return "Open Peer Connection Error", false, err } // Close the p2p before exit @@ -97,9 +93,7 @@ func (c *Core) CheckQuorumStatus(peerID string, did string) (string, bool, error var checkQuorumStatusResponse PingResponse err = p.SendJSONRequest("GET", APICheckQuorumStatusPath, q, nil, &checkQuorumStatusResponse, false, 2*time.Minute) if err != nil { - fmt.Println("Error in sending Json Request ", err) return "Send Json Request error ", false, err } - fmt.Println("core ping checkQuorumStatusResponse ", checkQuorumStatusResponse) return checkQuorumStatusResponse.Message, checkQuorumStatusResponse.Status, nil } diff --git a/core/quorum.go b/core/quorum.go index 21e626f8..c2b502b0 100644 --- a/core/quorum.go +++ b/core/quorum.go @@ -1,8 +1,6 @@ package core import ( - "fmt" - "github.com/rubixchain/rubixgoplatform/core/storage" "github.com/rubixchain/rubixgoplatform/core/wallet" "github.com/rubixchain/rubixgoplatform/wrapper/logger" @@ -68,8 +66,6 @@ func (qm *QuorumManager) GetQuorum(t int, lastChar string) []string { case QuorumTypeOne: var quorumList []wallet.DIDPeerMap err := qm.s.Read(wallet.DIDPeerStorage, &quorumList, "did_last_char=?", lastChar) - fmt.Println(quorumList) - if err != nil { qm.log.Error("Quorums not present") return nil @@ -79,7 +75,6 @@ func (qm *QuorumManager) GetQuorum(t int, lastChar string) []string { return nil } var quorumAddrList []string - fmt.Println(quorumAddrList) quorumCount := 0 for _, q := range quorumList { addr := string(q.PeerID + "." + q.DID) diff --git a/core/quorum_initiator.go b/core/quorum_initiator.go index 69c51dda..0c34a5cd 100644 --- a/core/quorum_initiator.go +++ b/core/quorum_initiator.go @@ -320,11 +320,8 @@ func (c *Core) initiateConsensus(cr *ConensusRequest, sc *contract.Contract, dc } var finalQl []string if cr.Type == 2 { - fmt.Println("quorum list with cr type 2 :") - fmt.Println(ql) finalQl = c.GetFinalQuorumList(ql) cr.QuorumList = finalQl - fmt.Println("Final groups with all quorums setup:", finalQl) } else { cr.QuorumList = ql } @@ -339,9 +336,6 @@ func (c *Core) initiateConsensus(cr *ConensusRequest, sc *contract.Contract, dc delete(c.pd, cr.ReqID) c.qlock.Unlock() }() - - fmt.Println("quorum list is ", ql, " length of ql is ", len(ql)) - for _, a := range cr.QuorumList { //This part of code is trying to connect to the quorums in quorum list, where various functions are called to pledge the tokens //and checking of transaction by the quorum i.e. consensus for the transaction. Once the quorum is connected, it pledges and @@ -765,7 +759,6 @@ func (c *Core) connectQuorum(cr *ConensusRequest, addr string, qt int, sc *contr var p *ipfsport.Peer var err error p, err = c.getPeer(addr) - fmt.Println("QuorumList in connect Quorum", cr.QuorumList) if err != nil { c.log.Error("Failed to get peer connection", "err", err) c.finishConsensus(cr.ReqID, qt, nil, false, "", nil, nil) @@ -865,7 +858,7 @@ func (c *Core) connectQuorum(cr *ConensusRequest, addr string, qt int, sc *contr var token string if tStart >= len(tokenPrefix) { token = cresp.Message[tStart:] - fmt.Println("Token is being Double spent. Token is ", token) + c.log.Debug("Token is being Double spent. Token is ", token) } doubleSpendTokenDetails, err2 := c.w.ReadToken(token) if err2 != nil { diff --git a/core/quorum_recv.go b/core/quorum_recv.go index dd87f4a3..f9a6f607 100644 --- a/core/quorum_recv.go +++ b/core/quorum_recv.go @@ -175,7 +175,6 @@ func (c *Core) quorumRBTConsensus(req *ensweb.Request, did string, qdc didcrypto tokenStateCheckResult := make([]TokenStateCheckResult, len(ti)) c.log.Debug("entering validation to check if token state is exhausted, ti len", len(ti)) - fmt.Println("Cr.QuorumList =", cr.QuorumList) for i := range ti { wg.Add(1) go c.checkTokenState(ti[i].Token, did, i, tokenStateCheckResult, &wg, cr.QuorumList, ti[i].TokenType) @@ -530,7 +529,6 @@ func (c *Core) quorumConensus(req *ensweb.Request) *ensweb.Result { return c.l.RenderJSON(req, &crep, http.StatusOK) } qdc, ok := c.qc[did] - fmt.Println("qdc in quorumreceiver core is ", qdc) if !ok { c.log.Error("Quorum is not setup") crep.Message = "Quorum is not setup" @@ -539,7 +537,6 @@ func (c *Core) quorumConensus(req *ensweb.Request) *ensweb.Result { switch cr.Mode { case RBTTransferMode: c.log.Debug("RBT consensus started") - fmt.Println("Cr.Quorumlist insie case RBTTransferMode =", cr.QuorumList) return c.quorumRBTConsensus(req, did, qdc, &cr) case DTCommitMode: c.log.Debug("Data consensus started") diff --git a/core/quorum_validation.go b/core/quorum_validation.go index 44ed9c1d..35613821 100644 --- a/core/quorum_validation.go +++ b/core/quorum_validation.go @@ -123,7 +123,8 @@ func (c *Core) syncParentToken(p *ipfsport.Peer, pt string) error { } if ptb.GetTransType() != block.TokenBurntType { issueType = ParentTokenNotBurned // parent token is not in burnt stage - fmt.Println("block state is ", ptb.GetTransTokens(), " expected value is ", block.TokenBurntType) + //Commenting gps + //fmt.Println("block state is ", ptb.GetTransTokens(), " expected value is ", block.TokenBurntType) c.log.Error("parent token is not in burnt stage", "token", pt) return fmt.Errorf("parent token is not in burnt stage. pt: %v, issueType: %v", pt, issueType) } @@ -360,7 +361,6 @@ func (c *Core) checkTokenState(tokenId, did string, index int, resultArray []Tok //check dht to see if any pin exist list, err1 := c.GetDHTddrs(tokenIDTokenStateHash) - fmt.Println("List in checkToken State", list) //try to call ipfs cat to check if any one has pinned the state i.e \ if err1 != nil { c.log.Error("Error fetching content for the tokenstate ipfs hash :", tokenIDTokenStateHash, "Error", err) @@ -384,11 +384,7 @@ func (c *Core) checkTokenState(tokenId, did string, index int, resultArray []Tok } qPeerIds = append(qPeerIds, pId) } - fmt.Println("QpeerIds in checkTokenState", qPeerIds) - updatedList := c.removeStrings(list, qPeerIds) - fmt.Println("Updated List in checkToken state", updatedList) - //if pin exist abort if len(updatedList) != 0 { c.log.Debug("Token state is exhausted, Token is being Double spent. Token : ", tokenId) diff --git a/core/smart_contract.go b/core/smart_contract.go index 130f6c22..d803b969 100644 --- a/core/smart_contract.go +++ b/core/smart_contract.go @@ -145,7 +145,7 @@ func (c *Core) generateSmartContractToken(requestID string, smartContractTokenRe return basicResponse } - fmt.Println("smartContractTokenHash ", smartContractTokenHash) + c.log.Info("smartContractTokenHash ", smartContractTokenHash) // Set the response status and message smartContractTokenResponse := &SmartContractTokenResponse{ diff --git a/server/basic.go b/server/basic.go index f799cb83..0212226f 100644 --- a/server/basic.go +++ b/server/basic.go @@ -1,7 +1,6 @@ package server import ( - "fmt" "net/http" "strings" "time" @@ -68,29 +67,22 @@ func (s *Server) APIPing(req *ensweb.Request) *ensweb.Result { // APIPing will ping to given peer func (s *Server) APICheckQuorumStatus(req *ensweb.Request) *ensweb.Result { - fmt.Println("APICheckQuorumStatus in basic.go") qAddress := s.GetQuerry(req, "quorumAddress") - fmt.Println("QuorumAddress", qAddress) // Split the string into two parts based on a delimiter parts := strings.Split(qAddress, ".") if len(parts) != 2 { // Handle the case where the string doesn't contain exactly two parts - fmt.Println("Invalid quorumAddress format") + s.log.Error("Invalid quorumAddress format, required format is PeerID.dID") return s.BasicResponse(req, false, "Invalid Quorum Address Format", nil) } // Assign the first part to "peerID" and the second part to "dID" peerID := parts[0] dID := parts[1] - - fmt.Println("peerid in basic " + peerID + " did is " + dID) str, status, err := s.c.CheckQuorumStatus(peerID, dID) if err != nil { s.log.Error("Quorum status check failed", "err", err) return s.BasicResponse(req, false, str, nil) } - /* if !status { - s.log.Error("Quorum setup is not done") - return s.BasicResponse(req, status, str, nil) - } */ + return s.BasicResponse(req, status, str, nil) } From 2bd283e1dd4607d43b878612b157956c89fa2a04 Mon Sep 17 00:00:00 2001 From: Allen Iype P Cherian Date: Thu, 2 May 2024 13:30:19 +0530 Subject: [PATCH 013/129] Fix: minor typo --- core/wallet/token.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/wallet/token.go b/core/wallet/token.go index 280ad255..09249119 100644 --- a/core/wallet/token.go +++ b/core/wallet/token.go @@ -562,7 +562,7 @@ func (w *Wallet) ReleaseAllLockedTokens() error { } if len(lockedTokens) == 0 { - w.log.Info("No Loked tokens to release") + w.log.Info("No locked tokens to release") return nil } for _, t := range lockedTokens { From 0be34767a5acab5512844a24d629858579d5ffeb Mon Sep 17 00:00:00 2001 From: Allen Iype P Cherian Date: Thu, 2 May 2024 17:43:19 +0530 Subject: [PATCH 014/129] Add proper error messages --- command/command.go | 2 +- core/diagnostic.go | 20 +++++++++++++++----- core/ping.go | 5 +++-- core/quorum_initiator.go | 11 ++++++++++- core/transfer.go | 4 ++-- 5 files changed, 31 insertions(+), 11 deletions(-) diff --git a/command/command.go b/command/command.go index 4f5a143f..9f68eb3e 100644 --- a/command/command.go +++ b/command/command.go @@ -33,7 +33,7 @@ const ( ) const ( - version string = "0.0.16b" + version string = "0.0.16" ) const ( VersionCmd string = "-v" diff --git a/core/diagnostic.go b/core/diagnostic.go index 7d555750..fe7a1090 100644 --- a/core/diagnostic.go +++ b/core/diagnostic.go @@ -1,6 +1,7 @@ package core import ( + "fmt" "strings" "time" @@ -207,10 +208,10 @@ func (c *Core) ReleaseAllLockedTokens() model.BasicResponse { return *response } -func (c *Core) GetFinalQuorumList(ql []string) []string { +func (c *Core) GetFinalQuorumList(ql []string) ([]string, error) { // Initialize finalQl as an empty slice to store the groups that meet the condition var finalQl []string - + var opError error // Loop through ql in groups of 5 items for i := 0; i < len(ql); i += 5 { end := i + 5 @@ -224,6 +225,7 @@ func (c *Core) GetFinalQuorumList(ql []string) []string { // Loop through the items in the group and check if their response message is "quorum is setup" for _, item := range group { + opError = nil parts := strings.Split(item, ".") if len(parts) != 2 { continue @@ -231,9 +233,11 @@ func (c *Core) GetFinalQuorumList(ql []string) []string { peerID := parts[0] did := parts[1] msg, _, err := c.CheckQuorumStatus(peerID, did) - if err != nil { + if err != nil || strings.Contains(msg, "Quorum Connection Error") { c.log.Error("Failed to check quorum status:", err) - continue + opError = fmt.Errorf("failed to check quorum status: %v", err) + allQuorumSetup = false + break } if msg != "Quorum is setup" { // If any item in the group does not have the response message as "quorum is setup", @@ -241,6 +245,12 @@ func (c *Core) GetFinalQuorumList(ql []string) []string { allQuorumSetup = false break } + if strings.Contains(msg, "Quorum is not setup") { + c.log.Error("quorums are currently unavailable for this trnx") + opError = fmt.Errorf("quorums are uncurrently available for this trnx") + allQuorumSetup = false + break + } } // If all items in the group have the response message as "quorum is setup", @@ -251,5 +261,5 @@ func (c *Core) GetFinalQuorumList(ql []string) []string { } } // Return finalQl - return finalQl + return finalQl, opError } diff --git a/core/ping.go b/core/ping.go index ea8d37e7..35b0e729 100644 --- a/core/ping.go +++ b/core/ping.go @@ -1,6 +1,7 @@ package core import ( + "fmt" "net/http" "time" @@ -68,7 +69,7 @@ func (c *Core) CheckQuorumStatusResponse(req *ensweb.Request) *ensweb.Result { / } _, ok := c.qc[did] if !ok { - c.log.Error("Quorum is not setup in core ping.go") + c.log.Error("Quorum is not setup") resp.Message = "Quorum is not setup" resp.Status = false return c.l.RenderJSON(req, &resp, http.StatusOK) @@ -85,7 +86,7 @@ func (c *Core) CheckQuorumStatus(peerID string, did string) (string, bool, error q := make(map[string]string) p, err := c.pm.OpenPeerConn(peerID, "", c.getCoreAppName(peerID)) if err != nil { - return "Open Peer Connection Error", false, err + return "Quorum Connection Error", false, fmt.Errorf("quorum connection error") } // Close the p2p before exit defer p.Close() diff --git a/core/quorum_initiator.go b/core/quorum_initiator.go index 0c34a5cd..45fd9735 100644 --- a/core/quorum_initiator.go +++ b/core/quorum_initiator.go @@ -319,9 +319,18 @@ func (c *Core) initiateConsensus(cr *ConensusRequest, sc *contract.Contract, dc return nil, nil, fmt.Errorf("failed to get required quorums") } var finalQl []string + var errFQL error if cr.Type == 2 { - finalQl = c.GetFinalQuorumList(ql) + finalQl, errFQL = c.GetFinalQuorumList(ql) + if errFQL != nil { + c.log.Error("unable to get consensus from quorum(s). err: ", errFQL) + return nil, nil, errFQL + } cr.QuorumList = finalQl + if len(finalQl) != MinQuorumRequired { + c.log.Error("quorum(s) are unavailable for this trnx") + return nil, nil, fmt.Errorf("quorum(s) are unavailable for this trnx. retry trnx after some time") + } } else { cr.QuorumList = ql } diff --git a/core/transfer.go b/core/transfer.go index 561ec229..d4b2f516 100644 --- a/core/transfer.go +++ b/core/transfer.go @@ -198,8 +198,8 @@ func (c *Core) initiateRBTTransfer(reqID string, req *model.RBTTransferRequest) } td, _, err := c.initiateConsensus(cr, sc, dc) if err != nil { - c.log.Error("Consensus failed", "err", err) - resp.Message = "Consensus failed" + err.Error() + c.log.Error("Consensus failed ", "err", err) + resp.Message = "Consensus failed " + err.Error() return resp } et := time.Now() From 47cef1789f71698d92ef201912e4a501004af293 Mon Sep 17 00:00:00 2001 From: Allen Iype P Cherian Date: Fri, 3 May 2024 11:40:20 +0530 Subject: [PATCH 015/129] Remove hardcoded quorum count --- core/diagnostic.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/core/diagnostic.go b/core/diagnostic.go index fe7a1090..f4eaa9ff 100644 --- a/core/diagnostic.go +++ b/core/diagnostic.go @@ -212,9 +212,9 @@ func (c *Core) GetFinalQuorumList(ql []string) ([]string, error) { // Initialize finalQl as an empty slice to store the groups that meet the condition var finalQl []string var opError error - // Loop through ql in groups of 5 items - for i := 0; i < len(ql); i += 5 { - end := i + 5 + // Loop through ql in groups of the Minimum Quorum Required + for i := 0; i < len(ql); i += MinQuorumRequired { + end := i + MinQuorumRequired if end > len(ql) { end = len(ql) } From 093646cdf2ae461568b7f13b58e322a59bfb65a0 Mon Sep 17 00:00:00 2001 From: Maneesha-rubix Date: Mon, 6 May 2024 15:40:58 +0530 Subject: [PATCH 016/129] updated Readme --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 2371d67c..f457f546 100644 --- a/README.md +++ b/README.md @@ -102,7 +102,7 @@ This following options are used for this command -port string Server/Host port (default "20000") -didType int - DID type (0-Light Mode, 1-Basic Mode, 2-Standard Mode, 3-Wallet Mode) (default 0) + DID type (0-Basic Mode, 1-Standard Mode, 2-Wallet Mode, 3-Child Mode, 4-Light Mode) (default 0) -didSecret string DID secret (default "My DID Secret") -privPWD string From babff64925f95f3d0ab1ecfa637cab91a6e5f46b Mon Sep 17 00:00:00 2001 From: Maneesha-rubix Date: Mon, 6 May 2024 16:28:25 +0530 Subject: [PATCH 017/129] changing variable and function names --- client/did.go | 12 ++++----- command/did.go | 4 +-- contract/contract.go | 2 +- core/core.go | 16 ++++++------ core/did.go | 4 +-- core/migrate.go | 2 +- core/part_token.go | 8 +++--- core/quorum_initiator.go | 10 ++++---- core/token_pin_check.go | 2 +- did/basic.go | 2 +- did/child.go | 2 +- did/did.go | 12 ++++----- did/{light.go => lite.go} | 34 ++++++++++++------------- did/model.go | 2 +- did/quorum.go | 2 +- did/{quorum_light.go => quorum_lite.go} | 8 +++--- did/standard.go | 2 +- did/wallet.go | 2 +- grpcclient/token.go | 2 +- grpcserver/did.go | 2 +- server/did.go | 4 +-- 21 files changed, 66 insertions(+), 68 deletions(-) rename did/{light.go => lite.go} (78%) rename did/{quorum_light.go => quorum_lite.go} (93%) diff --git a/client/did.go b/client/did.go index da91053d..de362662 100644 --- a/client/did.go +++ b/client/did.go @@ -48,11 +48,11 @@ func (c *Client) GetAllDIDs() (*model.GetAccountInfo, error) { } func (c *Client) CreateDID(cfg *did.DIDCreate) (string, bool) { - if cfg.Type < did.LightDIDMode && cfg.Type > did.WalletDIDMode { + if cfg.Type < did.LiteDIDMode && cfg.Type > did.WalletDIDMode { return "Invalid DID mode", false } switch cfg.Type { - case did.LightDIDMode: + case did.LiteDIDMode: cfg.PubKeyFile = "" case did.BasicDIDMode: if cfg.ImgFile == "" { @@ -126,7 +126,7 @@ func (c *Client) CreateDID(cfg *did.DIDCreate) (string, bool) { fields[setup.DIDConfigField] = string(jd) files := make(map[string]string) - if cfg.Type != did.LightDIDMode { + if cfg.Type != did.LiteDIDMode { if cfg.ImgFile != "" { files["image"] = cfg.ImgFile } @@ -156,12 +156,12 @@ func (c *Client) CreateDID(cfg *did.DIDCreate) (string, bool) { } func (c *Client) SetupDID(dc *did.DIDCreate) (string, bool) { - if dc.Type < did.BasicDIDMode && dc.Type > did.LightDIDMode { + if dc.Type < did.BasicDIDMode && dc.Type > did.LiteDIDMode { return "Invalid DID mode", false } switch dc.Type { - case did.LightDIDMode: + case did.LiteDIDMode: if !strings.Contains(dc.PubKeyFile, did.PubKeyFileName) || !strings.Contains(dc.PrivKeyFile, did.PvtKeyFileName) || !strings.Contains(dc.MnemonicFile, did.MnemonicFileName) { @@ -196,7 +196,7 @@ func (c *Client) SetupDID(dc *did.DIDCreate) (string, bool) { fields[setup.DIDConfigField] = string(jd) files := make(map[string]string) - if dc.Type != did.LightDIDMode { + if dc.Type != did.LiteDIDMode { if dc.PubImgFile != "" { files["pub_image"] = dc.PubImgFile } diff --git a/command/did.go b/command/did.go index 637d20fd..42d6fef0 100644 --- a/command/did.go +++ b/command/did.go @@ -50,7 +50,7 @@ func (cmd *Command) CreateDID() { } cmd.quorumPWD = pwd } - if cmd.didType == did.LightDIDMode { + if cmd.didType == did.LiteDIDMode { if cmd.privKeyFile == "" || cmd.pubKeyFile == "" { cmd.log.Error("private key & public key file names required") return @@ -254,7 +254,7 @@ func (cmd *Command) SignatureResponse(br *model.BasicResponse, timeout ...time.D Mode: sr.Mode, } switch sr.Mode { - case did.LightDIDMode: + case did.LiteDIDMode: sresp.Password = password case did.BasicDIDMode: sresp.Password = password diff --git a/contract/contract.go b/contract/contract.go index 2cd19d0c..d19334e3 100644 --- a/contract/contract.go +++ b/contract/contract.go @@ -446,7 +446,7 @@ func (c *Contract) VerifySignature(dc did.DIDCrypto) error { //If the ss i.e., share signature is empty, then its a Pki sign, so call PvtVerify //Else it is NLSS based sign, so call NlssVerify - didType := dc.GetSignVersion() + didType := dc.GetSignType() if didType == did.BIPVersion { ok, err := dc.PvtVerify([]byte(hs), util.StrToHex(ps)) diff --git a/core/core.go b/core/core.go index 8ceeff82..c337586f 100644 --- a/core/core.go +++ b/core/core.go @@ -508,8 +508,8 @@ func (c *Core) SetupDID(reqID string, didStr string) (did.DIDCrypto, error) { return nil, fmt.Errorf("faield to get did channel") } switch dt.Type { - case did.LightDIDMode: - return did.InitDIDLight(didStr, c.didDir, dc), nil + case did.LiteDIDMode: + return did.InitDIDLite(didStr, c.didDir, dc), nil case did.BasicDIDMode: return did.InitDIDBasic(didStr, c.didDir, dc), nil case did.StandardDIDMode: @@ -523,7 +523,7 @@ func (c *Core) SetupDID(reqID string, didStr string) (did.DIDCrypto, error) { } } -// Initializes the did in it's corresponding did mode (basic/ light) +// Initializes the did in it's corresponding did mode (basic/ lite) func (c *Core) SetupForienDID(didStr string) (did.DIDCrypto, error) { err := c.FetchDID(didStr) if err != nil { @@ -544,7 +544,7 @@ func (c *Core) SetupForienDID(didStr string) (did.DIDCrypto, error) { return c.InitialiseDID(didStr, didtype) } -// Initializes the quorum in it's corresponding did mode (basic/ light) +// Initializes the quorum in it's corresponding did mode (basic/ lite) func (c *Core) SetupForienDIDQuorum(didStr string) (did.DIDCrypto, error) { err := c.FetchDID(didStr) if err != nil { @@ -565,7 +565,7 @@ func (c *Core) SetupForienDIDQuorum(didStr string) (did.DIDCrypto, error) { switch didtype { case did.BasicDIDMode: return did.InitDIDQuorumc(didStr, c.didDir, ""), nil - case did.LightDIDMode: + case did.LiteDIDMode: return did.InitDIDQuorum_Lt(didStr, c.didDir, ""), nil default: return nil, fmt.Errorf("invalid did type") @@ -600,15 +600,15 @@ func (c *Core) GetPeerID() string { return c.peerID } -// Initializes the did in it's corresponding did mode (basic/ light) +// Initializes the did in it's corresponding did mode (basic/ lite) func (c *Core) InitialiseDID(didStr string, didType int) (did.DIDCrypto, error) { err := c.FetchDID(didStr) if err != nil { return nil, err } switch didType { - case did.LightDIDMode: - return did.InitDIDLight(didStr, c.didDir, nil), nil + case did.LiteDIDMode: + return did.InitDIDLite(didStr, c.didDir, nil), nil case did.BasicDIDMode: return did.InitDIDBasic(didStr, c.didDir, nil), nil default: diff --git a/core/did.go b/core/did.go index 95293e3c..5818135c 100644 --- a/core/did.go +++ b/core/did.go @@ -30,13 +30,13 @@ func (c *Core) GetDIDAccess(req *model.GetDIDAccess) *model.DIDAccessResponse { resp.Message = "Password does not match" return resp } - } else if dt.Type == did.LightDIDMode { + } else if dt.Type == did.LiteDIDMode { _, ok := c.ValidateDIDToken(req.Token, setup.ChanllegeTokenType, req.DID) if !ok { resp.Message = "Invalid token" return resp } - dc := did.InitDIDLight(req.DID, c.didDir, nil) + dc := did.InitDIDLite(req.DID, c.didDir, nil) ok, err := dc.PvtVerify([]byte(req.Token), req.Signature) if err != nil { c.log.Error("Failed to verify DID signature", "err", err) diff --git a/core/migrate.go b/core/migrate.go index 314125ba..cd55f0b0 100644 --- a/core/migrate.go +++ b/core/migrate.go @@ -164,7 +164,7 @@ func (c *Core) migrateNode(reqID string, m *MigrateRequest, didDir string) error QuorumPWD: m.QuorumPWD, } - if didCreate.Type != didm.LightDIDMode { + if didCreate.Type != didm.LiteDIDMode { didCreate = didm.DIDCreate{ DIDImgFileName: rubixDir + "DATA/" + d[0].DID + "/DID.png", PubImgFile: rubixDir + "DATA/" + d[0].DID + "/PublicShare.png", diff --git a/core/part_token.go b/core/part_token.go index 1e7aca3f..5e906911 100644 --- a/core/part_token.go +++ b/core/part_token.go @@ -96,7 +96,7 @@ func (c *Core) GetTokens(dc did.DIDCrypto, did string, value float64) ([]wallet. } idx := make([]int, 0) rpt := make([]wallet.Token, 0) - for i, _ := range pt { + for i := range pt { if pt[i].TokenValue <= rem { wt = append(wt, pt[i]) rem = floatPrecision(rem-pt[i].TokenValue, 10) @@ -169,7 +169,7 @@ func (c *Core) createPartToken(dc did.DIDCrypto, did string, tkn string, parts [ // check part split not crossing RBT amount := float64(0) - for i, _ := range parts { + for i := range parts { amount = amount + parts[i] amount = floatPrecision(amount, MaxDecimalPlaces) if amount > t.TokenValue { @@ -193,7 +193,7 @@ func (c *Core) createPartToken(dc did.DIDCrypto, did string, tkn string, parts [ c.log.Error("failed to get parent detials", "err", err) return nil, err } - for i, _ := range parts { + for i := range parts { rt := &rac.RacType{ Type: c.RACPartTokenType(), DID: did, @@ -303,7 +303,7 @@ func (c *Core) createPartToken(dc did.DIDCrypto, did string, tkn string, parts [ return nil, err } npt := make([]wallet.Token, 0) - for i, _ := range parts { + for i := range parts { ptkn := &wallet.Token{ TokenID: pts[i], ParentTokenID: tkn, diff --git a/core/quorum_initiator.go b/core/quorum_initiator.go index 45fd9735..a21aa6ed 100644 --- a/core/quorum_initiator.go +++ b/core/quorum_initiator.go @@ -182,11 +182,11 @@ func (c *Core) SetupQuorum(didStr string, pwd string, pvtKeyPwd string) error { } //To support NLSS backward compatibility, - //If the Quorum's did is created in light mode, + //If the Quorum's did is created in lite mode, //it will initiate DIDQuorum_Lt, and if it is in basic mode, //it will initiate DIDQuorumc switch dt.Type { - case did.LightDIDMode: + case did.LiteDIDMode: dc := did.InitDIDQuorum_Lt(didStr, c.didDir, pwd) if dc == nil { c.log.Error("Failed to setup quorum") @@ -194,7 +194,7 @@ func (c *Core) SetupQuorum(didStr string, pwd string, pvtKeyPwd string) error { } c.qc[didStr] = dc if pvtKeyPwd != "" { - dc := did.InitDIDLightWithPassword(didStr, c.didDir, pvtKeyPwd) + dc := did.InitDIDLiteWithPassword(didStr, c.didDir, pvtKeyPwd) if dc == nil { c.log.Error("Failed to setup quorum as dc is nil") return fmt.Errorf("failed to setup quorum") @@ -722,7 +722,7 @@ func (c *Core) finishConsensus(id string, qt int, p *ipfsport.Peer, status bool, var signVersion string - //signVersion = 0 => Pki based sign in light mode + //signVersion = 0 => Pki based sign in lite mode //signVersion = 1 => Nlss based sign in basic mode if util.HexToStr(ss) == "" { signVersion = "0" @@ -983,7 +983,7 @@ func (c *Core) pledgeQuorumToken(cr *ConensusRequest, sc *contract.Contract, tid c.log.Error("failed to fetch sender sign", "err", err) return nil, fmt.Errorf("failed to fetch sender sign") } - sender_sign_version := dc.GetSignVersion() + sender_sign_version := dc.GetSignType() sender_sign_ := &SenderSignature{ NLSS_share: sender_share_sign, Private_sign: sender_priv_sign, diff --git a/core/token_pin_check.go b/core/token_pin_check.go index c6d50984..e1306369 100644 --- a/core/token_pin_check.go +++ b/core/token_pin_check.go @@ -114,7 +114,7 @@ func (c *Core) pinCheck(token string, index int, senderPeerId string, receiverPe } } - for peerId := range peerIdRolemap { + for peerId, _ := range peerIdRolemap { if peerIdRolemap[peerId] == wallet.OwnerRole { c.log.Error("Token has multiple Pins") result.Status = true diff --git a/did/basic.go b/did/basic.go index 589c5a6f..6a901cec 100644 --- a/did/basic.go +++ b/did/basic.go @@ -65,7 +65,7 @@ func (d *DIDBasic) GetDID() string { // When the did creation and signing is done in Basic mode, // this function returns the sign version as NLSSVersion = 1 -func (d *DIDBasic) GetSignVersion() int { +func (d *DIDBasic) GetSignType() int { return NlssVersion } diff --git a/did/child.go b/did/child.go index 342ab3d8..cc2f08c5 100644 --- a/did/child.go +++ b/did/child.go @@ -66,7 +66,7 @@ func (d *DIDChild) GetDID() string { // When the did creation and signing is done in Child mode, // this function returns the sign version as NLSSVersion = 1 -func (d *DIDChild) GetSignVersion() int { +func (d *DIDChild) GetSignType() int { return NlssVersion } diff --git a/did/did.go b/did/did.go index fabaacd6..7edf5ba7 100644 --- a/did/did.go +++ b/did/did.go @@ -40,7 +40,7 @@ type DID struct { type DIDCrypto interface { GetDID() string - GetSignVersion() int + GetSignType() int Sign(hash string) ([]byte, []byte, error) NlssVerify(hash string, didSig []byte, pvtSig []byte) (bool, error) PvtSign(hash []byte) ([]byte, error) @@ -72,8 +72,8 @@ func (d *DID) CreateDID(didCreate *DIDCreate) (string, error) { return "", err } - //In light mode, did is simply the SHA-256 hash of the public key - if didCreate.Type == LightDIDMode { + //In lite mode, did is simply the SHA-256 hash of the public key + if didCreate.Type == LiteDIDMode { if didCreate.PrivPWD == "" { d.log.Error("password required for creating", "err", err) return "", err @@ -270,7 +270,7 @@ func (d *DID) CreateDID(didCreate *DIDCreate) (string, error) { if err != nil { return "", err } - } else if didCreate.Type != LightDIDMode { + } else if didCreate.Type != LiteDIDMode { if didCreate.QuorumPWD == "" { if didCreate.PrivPWD != "" { didCreate.QuorumPWD = didCreate.PrivPWD @@ -342,7 +342,7 @@ func (d *DID) MigrateDID(didCreate *DIDCreate) (string, error) { return "", err } - if didCreate.Type != LightDIDMode { + if didCreate.Type != LiteDIDMode { _, err = util.Filecopy(didCreate.DIDImgFileName, dirName+"/public/"+DIDImgFileName) if err != nil { d.log.Error("failed to copy did image", "err", err) @@ -407,7 +407,7 @@ func (d *DID) MigrateDID(didCreate *DIDCreate) (string, error) { } } - if didCreate.Type != LightDIDMode { + if didCreate.Type != LiteDIDMode { if didCreate.QuorumPrivKeyFile == "" || didCreate.QuorumPubKeyFile == "" { pvtKey, pubKey, err := crypto.GenerateKeyPair(&crypto.CryptoConfig{Alg: crypto.ECDSAP256, Pwd: didCreate.QuorumPWD}) if err != nil { diff --git a/did/light.go b/did/lite.go similarity index 78% rename from did/light.go rename to did/lite.go index d3f11890..beccd88a 100644 --- a/did/light.go +++ b/did/lite.go @@ -12,24 +12,24 @@ import ( "github.com/rubixchain/rubixgoplatform/util" ) -// DIDLight will handle Light DID -type DIDLight struct { +// DIDLite will handle Light DID +type DIDLite struct { did string dir string ch *DIDChan pwd string } -// InitDIDLight will return the Light did handle -func InitDIDLight(did string, baseDir string, ch *DIDChan) *DIDLight { - return &DIDLight{did: did, dir: util.SanitizeDirPath(baseDir) + did + "/", ch: ch} +// InitDIDLite will return the Light did handle +func InitDIDLite(did string, baseDir string, ch *DIDChan) *DIDLite { + return &DIDLite{did: did, dir: util.SanitizeDirPath(baseDir) + did + "/", ch: ch} } -func InitDIDLightWithPassword(did string, baseDir string, pwd string) *DIDLight { - return &DIDLight{did: did, dir: util.SanitizeDirPath(baseDir) + did + "/", pwd: pwd} +func InitDIDLiteWithPassword(did string, baseDir string, pwd string) *DIDLite { + return &DIDLite{did: did, dir: util.SanitizeDirPath(baseDir) + did + "/", pwd: pwd} } -func (d *DIDLight) getPassword() (string, error) { +func (d *DIDLite) getPassword() (string, error) { if d.pwd != "" { return d.pwd, nil } @@ -41,7 +41,7 @@ func (d *DIDLight) getPassword() (string, error) { Message: "Password needed", Result: SignReqData{ ID: d.ch.ID, - Mode: LightDIDMode, + Mode: LiteDIDMode, }, } d.ch.OutChan <- sr @@ -60,19 +60,19 @@ func (d *DIDLight) getPassword() (string, error) { return d.pwd, nil } -func (d *DIDLight) GetDID() string { +func (d *DIDLite) GetDID() string { return d.did } // When the did creation and signing is done in Light mode, // this function returns the sign version as BIPVersion = 0 -func (d *DIDLight) GetSignVersion() int { +func (d *DIDLite) GetSignType() int { return BIPVersion } -// PKI based sign in light mode -// In light mode, the sign function returns only the private signature, unlike the basic mode -func (d *DIDLight) Sign(hash string) ([]byte, []byte, error) { +// PKI based sign in lite mode +// In lite mode, the sign function returns only the private signature, unlike the basic mode +func (d *DIDLite) Sign(hash string) ([]byte, []byte, error) { pvtKeySign, err := d.PvtSign([]byte(hash)) bs := []byte{} @@ -80,7 +80,7 @@ func (d *DIDLight) Sign(hash string) ([]byte, []byte, error) { } // verify nlss based signatures -func (d *DIDLight) NlssVerify(hash string, pvtShareSig []byte, pvtKeySIg []byte) (bool, error) { +func (d *DIDLite) NlssVerify(hash string, pvtShareSig []byte, pvtKeySIg []byte) (bool, error) { //read senderDID didImg, err := util.GetPNGImagePixels(d.dir + DIDImgFileName) if err != nil { @@ -135,7 +135,7 @@ func (d *DIDLight) NlssVerify(hash string, pvtShareSig []byte, pvtKeySIg []byte) } -func (d *DIDLight) PvtSign(hash []byte) ([]byte, error) { +func (d *DIDLite) PvtSign(hash []byte) ([]byte, error) { privKey, err := ioutil.ReadFile(d.dir + PvtKeyFileName) if err != nil { return nil, err @@ -161,7 +161,7 @@ func (d *DIDLight) PvtSign(hash []byte) ([]byte, error) { } // Verify PKI based signature -func (d *DIDLight) PvtVerify(hash []byte, sign []byte) (bool, error) { +func (d *DIDLite) PvtVerify(hash []byte, sign []byte) (bool, error) { pubKey, err := ioutil.ReadFile(d.dir + PubKeyFileName) if err != nil { return false, err diff --git a/did/model.go b/did/model.go index 2496fda0..bf18b21f 100644 --- a/did/model.go +++ b/did/model.go @@ -5,7 +5,7 @@ const ( StandardDIDMode WalletDIDMode ChildDIDMode - LightDIDMode + LiteDIDMode ) const ( diff --git a/did/quorum.go b/did/quorum.go index 3b964b68..d1955d8c 100644 --- a/did/quorum.go +++ b/did/quorum.go @@ -48,7 +48,7 @@ func (d *DIDQuorum) GetDID() string { return d.did } -func (d *DIDQuorum) GetSignVersion() int { +func (d *DIDQuorum) GetSignType() int { return NlssVersion } diff --git a/did/quorum_light.go b/did/quorum_lite.go similarity index 93% rename from did/quorum_light.go rename to did/quorum_lite.go index 9f9f6fe0..a56f7172 100644 --- a/did/quorum_light.go +++ b/did/quorum_lite.go @@ -11,7 +11,7 @@ import ( "github.com/rubixchain/rubixgoplatform/util" ) -// DIDQuorum_Lt will handle light DID +// DIDQuorum_Lt will handle lite DID type DIDQuorum_Lt struct { did string dir string @@ -20,7 +20,7 @@ type DIDQuorum_Lt struct { pubKey crypto.PublicKey } -// InitDIDQuorum_Lt will return the Quorum did handle in light mode +// InitDIDQuorum_Lt will return the Quorum did handle in lite mode func InitDIDQuorum_Lt(did string, baseDir string, pwd string) *DIDQuorum_Lt { d := &DIDQuorum_Lt{did: did, dir: util.SanitizeDirPath(baseDir) + did + "/", pwd: pwd} if d.pwd != "" { @@ -49,9 +49,7 @@ func (d *DIDQuorum_Lt) GetDID() string { return d.did } -// When the did creation and signing is done in Light mode, -// this function returns the sign version as BIPVersion = 0 -func (d *DIDQuorum_Lt) GetSignVersion() int { +func (d *DIDQuorum_Lt) GetSignType() int { return BIPVersion } diff --git a/did/standard.go b/did/standard.go index a3644369..90154f3b 100644 --- a/did/standard.go +++ b/did/standard.go @@ -57,7 +57,7 @@ func (d *DIDStandard) GetDID() string { // When the did creation and signing is done in Standard mode, // this function returns the sign version as NLSSVersion = 1 -func (d *DIDStandard) GetSignVersion() int { +func (d *DIDStandard) GetSignType() int { return NlssVersion } diff --git a/did/wallet.go b/did/wallet.go index 8b1c423f..59385414 100644 --- a/did/wallet.go +++ b/did/wallet.go @@ -58,7 +58,7 @@ func (d *DIDWallet) GetDID() string { // When the did creation and signing is done in wallet mode, // this function returns the sign version as NLSSVersion = 1 -func (d *DIDWallet) GetSignVersion() int { +func (d *DIDWallet) GetSignType() int { return NlssVersion } diff --git a/grpcclient/token.go b/grpcclient/token.go index 19dfbcee..77370d25 100644 --- a/grpcclient/token.go +++ b/grpcclient/token.go @@ -34,7 +34,7 @@ func (cmd *Command) GenerateRBT() { Mode: br.SignRequest.Mode, } switch int(br.SignRequest.Mode) { - case did.LightDIDMode: + case did.LiteDIDMode: resp.Password = cmd.privPWD case did.BasicDIDMode: resp.Password = cmd.privPWD diff --git a/grpcserver/did.go b/grpcserver/did.go index ddbede05..21606ed0 100644 --- a/grpcserver/did.go +++ b/grpcserver/did.go @@ -85,7 +85,7 @@ func (rn *RubixNative) CreateDID(ctx context.Context, req *protos.CreateDIDReq) } defer os.RemoveAll(folderName) - if dc.Type != did.LightDIDMode { + if dc.Type != did.LiteDIDMode { if req.DidImage != "" { err = createFile(folderName+"/"+did.DIDImgFileName, req.DidImage, true) if err != nil { diff --git a/server/did.go b/server/did.go index b77ba3f4..777a2835 100644 --- a/server/did.go +++ b/server/did.go @@ -67,7 +67,7 @@ func (s *Server) APICreateDID(req *ensweb.Request) *ensweb.Result { didCreate.PubKeyFile = fileName } - if didCreate.Type != did.LightDIDMode { + if didCreate.Type != did.LiteDIDMode { if strings.Contains(fileName, did.ImgFileName) { didCreate.ImgFile = fileName } @@ -211,7 +211,7 @@ func (s *Server) APISetupDID(req *ensweb.Request) *ensweb.Result { didCreate.PubKeyFile = fileName } - if didCreate.Type != did.LightDIDMode { + if didCreate.Type != did.LiteDIDMode { if strings.Contains(fileName, did.DIDImgFileName) { didCreate.DIDImgFileName = fileName } From 586b7a5afbae13b5fc37b96331c558902fcdcc32 Mon Sep 17 00:00:00 2001 From: Maneesha-rubix Date: Wed, 8 May 2024 14:18:09 +0530 Subject: [PATCH 018/129] ping peer to get peer did type --- core/core.go | 27 ++++++++++++++++++++---- core/model/basic.go | 6 ++++++ core/ping.go | 50 +++++++++++++++++++++++++++++++++++++++++++++ core/wallet/did.go | 37 +++++++++++++++++++++++++-------- 4 files changed, 108 insertions(+), 12 deletions(-) diff --git a/core/core.go b/core/core.go index c337586f..537de591 100644 --- a/core/core.go +++ b/core/core.go @@ -47,6 +47,7 @@ const ( APIGetMigratedTokenStatus string = "/api/get-Migrated-token-status" APISyncDIDArbitration string = "/api/sync-did-arbitration" APICheckQuorumStatusPath string = "/api/check-quorum-status" + APIGetPeerDIDTypePath string = "/api/get-peer-didType" ) const ( @@ -320,6 +321,7 @@ func (c *Core) SetupCore() error { c.w.SetupWallet(c.ipfs) c.PingSetup() c.CheckQuorumStatusSetup() + c.GetPeerdidTypeSetup() c.peerSetup() c.w.AddDIDLastChar() c.SetupToken() @@ -554,12 +556,29 @@ func (c *Core) SetupForienDIDQuorum(didStr string) (did.DIDCrypto, error) { // Fetching peer's did type from PeerDIDTable using GetPeerDIDType function // and own did type from DIDTable using GetDID function didtype, err := c.w.GetPeerDIDType(didStr) - if err != nil { + if err != nil || didtype == -1 { dt, err1 := c.w.GetDID(didStr) - if err1 != nil { - return nil, fmt.Errorf("couldn't fetch did type") + + if err1 != nil || dt.Type == -1 { + peerId := c.w.GetPeerID(didStr) + + if peerId == "" { + return nil, err + } + didtype_, msg, err2 := c.GetPeerdidType_fromPeer(peerId, didStr) + if err2 != nil { + c.log.Error(msg) + return nil, err2 + } + didtype = didtype_ + peerUpdateResult, err3 := c.w.UpdatePeerDIDType(didStr, didtype) + if !peerUpdateResult { + c.log.Error("couldn't update did type in peer did table", err3) + } + } else { + didtype = dt.Type } - didtype = dt.Type + } switch didtype { diff --git a/core/model/basic.go b/core/model/basic.go index 65493651..eb70deaa 100644 --- a/core/model/basic.go +++ b/core/model/basic.go @@ -20,3 +20,9 @@ type MigratedTokenStatus struct { Message string `json:"message"` MigratedStatus []int `json:"migratedstatus"` } + +// GetDIDTypeResponse is the model for response of peer while fetching did type +type GetDIDTypeResponse struct { + DidType int + BasicResponse +} diff --git a/core/ping.go b/core/ping.go index 35b0e729..4d0731f0 100644 --- a/core/ping.go +++ b/core/ping.go @@ -29,6 +29,11 @@ func (c *Core) CheckQuorumStatusSetup() { c.l.AddRoute(APICheckQuorumStatusPath, "GET", c.CheckQuorumStatusResponse) } +// GetPeerdidTypeSetup will setup the ping route +func (c *Core) GetPeerdidTypeSetup() { + c.l.AddRoute(APIGetPeerDIDTypePath, "GET", c.GetPeerdidTypeResponse) +} + // PingRecevied is the handler for ping request func (c *Core) PingRecevied(req *ensweb.Request) *ensweb.Result { c.log.Info("Ping Received") @@ -98,3 +103,48 @@ func (c *Core) CheckQuorumStatus(peerID string, did string) (string, bool, error } return checkQuorumStatusResponse.Message, checkQuorumStatusResponse.Status, nil } + +// CheckQuorumStatusResponse is the handler for CheckQuorumStatus request +func (c *Core) GetPeerdidTypeResponse(req *ensweb.Request) *ensweb.Result { //PingRecevied + did := c.l.GetQuerry(req, "did") + c.log.Info("Fetching peer did type from peer") + resp := &model.GetDIDTypeResponse{ + BasicResponse: model.BasicResponse{ + Status: false, + }, + } + + dt, err := c.w.GetDID(did) + if err != nil { + c.log.Error("Couldn't fetch did type from DID Table", "error", err) + resp.Message = "Couldn't fetch did type for did: " + did + resp.Status = false + resp.DidType = -1 + return c.l.RenderJSON(req, &resp, http.StatusOK) + } else { + resp.DidType = dt.Type + resp.Status = true + resp.Message = "successfully fetched did type" + return c.l.RenderJSON(req, &resp, http.StatusOK) + } + +} + +// GetPeerdidType will ping the peer & get the did type +func (c *Core) GetPeerdidType_fromPeer(peerID string, did string) (int, string, error) { + q := make(map[string]string) + p, err := c.pm.OpenPeerConn(peerID, did, c.getCoreAppName(peerID)) + if err != nil { + return -1, "Quorum Connection Error", fmt.Errorf("quorum connection error") + } + + // Close the p2p before exit + defer p.Close() + q["did"] = did + var getPeerdidTypeResponse model.GetDIDTypeResponse + err = p.SendJSONRequest("GET", APIGetPeerDIDTypePath, q, nil, &getPeerdidTypeResponse, false, 2*time.Minute) + if err != nil { + return -1, "Send Json Request error ", err + } + return getPeerdidTypeResponse.DidType, getPeerdidTypeResponse.Message, nil +} diff --git a/core/wallet/did.go b/core/wallet/did.go index daadf251..798bd84a 100644 --- a/core/wallet/did.go +++ b/core/wallet/did.go @@ -1,7 +1,5 @@ package wallet -import "fmt" - type DIDType struct { DID string `gorm:"column:did;primaryKey"` Type int `gorm:"column:type"` @@ -12,7 +10,7 @@ type DIDType struct { type DIDPeerMap struct { DID string `gorm:"column:did;primaryKey"` - DIDType int `gorm:"column:did_type"` + DIDType *int `gorm:"column:did_type"` PeerID string `gorm:"column:peer_id"` DIDLastChar string `gorm:"column:did_last_char"` } @@ -97,15 +95,15 @@ func (w *Wallet) AddDIDPeerMap(did string, peerID string, didType int) error { dm.DID = did dm.PeerID = peerID dm.DIDLastChar = lastChar - dm.DIDType = didType + dm.DIDType = &didType return w.s.Write(DIDPeerStorage, &dm) } if dm.PeerID != peerID { dm.PeerID = peerID return w.s.Update(DIDPeerStorage, &dm, "did=?", did) } - if dm.DIDType == 0 { - dm.DIDType = didType + if dm.DIDType == nil { + dm.DIDType = &didType return w.s.Update(DIDPeerStorage, &dm, "did=?", did) } return nil @@ -144,7 +142,30 @@ func (w *Wallet) GetPeerDIDType(did string) (int, error) { var dm DIDPeerMap err := w.s.Read(DIDPeerStorage, &dm, "did=?", did) if err != nil { - return 5, fmt.Errorf("couldn't fetch did type from peer did table") + w.log.Error("couldn't fetch did type from peer did table") + return -1, err + } + if dm.DIDType == nil { + return -1, nil + } + return *dm.DIDType, nil +} + +// Updates did type of the given did in PeerDIDTable +func (w *Wallet) UpdatePeerDIDType(did string, didtype int) (bool, error) { + var dm DIDPeerMap + err := w.s.Read(DIDPeerStorage, &dm, "did=?", did) + if err != nil { + w.log.Error("couldn't read from peer did table") + return false, err + } + + dm.DIDType = &didtype + + err1 := w.s.Update(DIDPeerStorage, &dm, "did=?", did) + if err1 != nil { + w.log.Error("couldn't update did type in peer did table") + return false, err1 } - return dm.DIDType, nil + return true, nil } From f0849cde57f9f527764f3d9cb84b37f1820e3d9a Mon Sep 17 00:00:00 2001 From: Maneesha-rubix Date: Mon, 13 May 2024 16:59:02 +0530 Subject: [PATCH 019/129] tested port-unavailability-fix on MacOs --- core/ipfsport/peer.go | 3 --- 1 file changed, 3 deletions(-) diff --git a/core/ipfsport/peer.go b/core/ipfsport/peer.go index b5837baa..cee13a43 100644 --- a/core/ipfsport/peer.go +++ b/core/ipfsport/peer.go @@ -70,11 +70,8 @@ func (pm *PeerManager) getPeerPort() uint16 { availability := isPortAvailable(port) if availability { - fmt.Println("available port: ", port, availability) pm.ps[i] = true return pm.startPort + uint16(i) - } else { - fmt.Println("NOT available port: ", port, availability) } } } From bd7b94c4e4cc1ebd8af97d84e8c7a658653fdb75 Mon Sep 17 00:00:00 2001 From: Maneesha-rubix Date: Wed, 15 May 2024 13:40:53 +0530 Subject: [PATCH 020/129] change field name SignVersion to SignType --- core/quorum_initiator.go | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/core/quorum_initiator.go b/core/quorum_initiator.go index a21aa6ed..3351832d 100644 --- a/core/quorum_initiator.go +++ b/core/quorum_initiator.go @@ -128,7 +128,7 @@ type CreditSignature struct { PrivSignature string `json:"priv_signature"` DID string `json:"did"` Hash string `json:"hash"` - SignVersion string `json:"sign_version"` //represents sign version (PkiSign == 0 or NlssSign==1) + SignType string `json:"sign_type"` //represents sign type (PkiSign == 0 or NlssSign==1) } type SenderSignature struct { @@ -136,7 +136,7 @@ type SenderSignature struct { Private_sign string `json:"priv_signature"` DID string `json:"sender_did"` Hash string `json:"hash"` - SignVersion int `json:"sign_version"` //represents sign version (PkiSign == 0 or NlssSign==1) + SignType int `json:"sign_type"` //represents sign type (PkiSign == 0 or NlssSign==1) } type TokenArbitrationReq struct { @@ -720,14 +720,14 @@ func (c *Core) finishConsensus(id string, qt int, p *ipfsport.Peer, status bool, return } - var signVersion string + var signType string - //signVersion = 0 => Pki based sign in lite mode - //signVersion = 1 => Nlss based sign in basic mode + //signType = 0 => Pki based sign in lite mode + //signType = 1 => Nlss based sign in basic mode if util.HexToStr(ss) == "" { - signVersion = "0" + signType = "0" } else { - signVersion = "1" + signType = "1" } switch qt { @@ -741,7 +741,7 @@ func (c *Core) finishConsensus(id string, qt int, p *ipfsport.Peer, status bool, PrivSignature: util.HexToStr(ps), DID: did, Hash: hash, - SignVersion: signVersion, + SignType: signType, } cs.P[did] = p cs.Credit.Credit = append(cs.Credit.Credit, csig) @@ -983,13 +983,13 @@ func (c *Core) pledgeQuorumToken(cr *ConensusRequest, sc *contract.Contract, tid c.log.Error("failed to fetch sender sign", "err", err) return nil, fmt.Errorf("failed to fetch sender sign") } - sender_sign_version := dc.GetSignType() + sender_sign_type := dc.GetSignType() sender_sign_ := &SenderSignature{ NLSS_share: sender_share_sign, Private_sign: sender_priv_sign, DID: senderdid, Hash: sign_data, - SignVersion: sender_sign_version, + SignType: sender_sign_type, } sender_sign, err := json.Marshal(sender_sign_) if err != nil { From de674f72cd206407b6896851e37e37eaec80f846 Mon Sep 17 00:00:00 2001 From: Vaishnav CH Date: Wed, 15 May 2024 16:32:01 +0530 Subject: [PATCH 021/129] Modify the condition statement --- core/unpledge.go | 20 +++++++++++--------- core/unpledge/unpledge.go | 20 +++++++++++--------- 2 files changed, 22 insertions(+), 18 deletions(-) diff --git a/core/unpledge.go b/core/unpledge.go index a4cba3d6..388a6662 100644 --- a/core/unpledge.go +++ b/core/unpledge.go @@ -15,16 +15,18 @@ func (c *Core) Unpledge(t string, file string) error { c.log.Error("Failed to fetch unpledge token details fot token ", t, " error : ", err) } var tokenType int - if unpledgetokendetails.TokenValue == 1.0 { - tokenType = token.RBTTokenType + if c.testNet { + if unpledgetokendetails.TokenValue == 1 { + tokenType = token.TestTokenType + } else if unpledgetokendetails.TokenValue < 1 { + tokenType = token.TestPartTokenType + } } else { - tokenType = token.PartTokenType - } - - if c.testNet && unpledgetokendetails.TokenValue == 1.0 { - tokenType = token.TestTokenType - } else { - tokenType = token.TestPartTokenType + if unpledgetokendetails.TokenValue == 1 { + tokenType = token.RBTTokenType + } else if unpledgetokendetails.TokenValue < 1 { + tokenType = token.PartTokenType + } } b := c.w.GetLatestTokenBlock(t, tokenType) if b == nil { diff --git a/core/unpledge/unpledge.go b/core/unpledge/unpledge.go index edaaa331..9b119ef0 100644 --- a/core/unpledge/unpledge.go +++ b/core/unpledge/unpledge.go @@ -164,16 +164,18 @@ func (up *UnPledge) runUnpledge() { continue } var tt int - if unpledgetokendetails.TokenValue == 1.0 { - tt = token.RBTTokenType - } else { - tt = token.PartTokenType - } - - if up.testNet && unpledgetokendetails.TokenValue == 1.0 { - tt = token.TestTokenType + if up.testNet { + if unpledgetokendetails.TokenValue == 1 { + tt = token.TestTokenType + } else if unpledgetokendetails.TokenValue < 1 { + tt = token.TestPartTokenType + } } else { - tt = token.TestPartTokenType + if unpledgetokendetails.TokenValue == 1 { + tt = token.RBTTokenType + } else if unpledgetokendetails.TokenValue < 1 { + tt = token.PartTokenType + } } b := up.w.GetLatestTokenBlock(t, tt) if b == nil { From a289364c43028f0ac6bee2251651e658d9c71bf4 Mon Sep 17 00:00:00 2001 From: Ashita Gupta Date: Mon, 20 May 2024 16:48:26 +0530 Subject: [PATCH 022/129] Adding Peer Details Manually --- client/addpeer.go | 17 +++++++++ command/addingpeerdetails.go | 69 ++++++++++++++++++++++++++++++++++++ command/command.go | 7 +++- core/peer.go | 10 ++++++ docs/docs.go | 51 ++++++++++++++++++++++++-- docs/swagger.json | 48 +++++++++++++++++++++++++ docs/swagger.yaml | 31 ++++++++++++++++ server/addpeer.go | 49 +++++++++++++++++++++++++ server/server.go | 2 +- setup/setup.go | 1 + 10 files changed, 281 insertions(+), 4 deletions(-) create mode 100644 client/addpeer.go create mode 100644 command/addingpeerdetails.go create mode 100644 server/addpeer.go diff --git a/client/addpeer.go b/client/addpeer.go new file mode 100644 index 00000000..39d3c505 --- /dev/null +++ b/client/addpeer.go @@ -0,0 +1,17 @@ +package client + +import ( + "github.com/rubixchain/rubixgoplatform/core/model" + "github.com/rubixchain/rubixgoplatform/core/wallet" + "github.com/rubixchain/rubixgoplatform/setup" +) + +func (c *Client) AddPeer(peer_detail *wallet.DIDPeerMap) (string, bool) { + + var rm model.BasicResponse + err := c.sendJSONRequest("POST", setup.APIAddPeerDetails, nil, &peer_detail, &rm) + if err != nil { + return err.Error(), false + } + return rm.Message, rm.Status +} diff --git a/command/addingpeerdetails.go b/command/addingpeerdetails.go new file mode 100644 index 00000000..6c77d72d --- /dev/null +++ b/command/addingpeerdetails.go @@ -0,0 +1,69 @@ +package command + +import ( + "fmt" + "strings" + + "github.com/rubixchain/rubixgoplatform/core/wallet" +) + +func (cmd *Command) AddPeerDetails() { + var peerID string + var did string + var did_type int + var err error + if cmd.peerID == "" { + fmt.Print("Enter PeerID : ") + _, err = fmt.Scan(&peerID) + if err != nil { + cmd.log.Error("Failed to get PeerID") + return + } + + } else { + peerID = cmd.peerID + } + + if !strings.HasPrefix(peerID, "12D3KooW") || len(peerID) < 52 { + cmd.log.Error("Invalid PeerID") + return + } + + if cmd.did == "" { + fmt.Print("Enter DID : ") + _, err = fmt.Scan(&did) + if err != nil { + cmd.log.Error("Failed to get DID") + return + } + } else { + did = cmd.did + } + if !strings.HasPrefix(did, "bafybmi") || len(did) < 59 { + cmd.log.Error("Invalid DID") + return + } + + fmt.Print("Enter DID Type : ") + _, err = fmt.Scan(&did_type) + if err != nil { + cmd.log.Error("Invalid DID Type") + return + } + if did_type < 0 || did_type > 4 { + cmd.log.Error("DID should be between 0 and 4") + return + } + + peer_detail := wallet.DIDPeerMap{ + PeerID: peerID, + DID: did, + DIDType: &did_type, + } + msg, status := cmd.c.AddPeer(&peer_detail) + if !status { + cmd.log.Error("Failed to add peer in DB", "message", msg) + return + } + cmd.log.Info("Peer added successfully") +} diff --git a/command/command.go b/command/command.go index 9f68eb3e..98f7533d 100644 --- a/command/command.go +++ b/command/command.go @@ -81,6 +81,7 @@ const ( AddExplorerCmd string = "addexplorer" RemoveExplorerCmd string = "removeexplorer" GetAllExplorerCmd string = "getallexplorer" + AddPeerDetailsCmd string = "addpeerdetails" ) var commands = []string{VersionCmd, @@ -126,6 +127,7 @@ var commands = []string{VersionCmd, GetTokenBlock, GetSmartContractData, CheckQuorumStatusCmd, + AddPeerDetailsCmd, } var commandsHelp = []string{"To get tool version", "To get help", @@ -168,7 +170,8 @@ var commandsHelp = []string{"To get tool version", "This command will subscribe to a smart contract token", "This command will dump the smartcontract token chain", "This command gets token block", - "This command gets the smartcontract data from latest block"} + "This command gets the smartcontract data from latest block", + "This command is to add the peer details manually"} type Command struct { cfg config.Config @@ -597,6 +600,8 @@ func Run(args []string) { cmd.removeExplorer() case GetAllExplorerCmd: cmd.getAllExplorer() + case AddPeerDetailsCmd: + cmd.AddPeerDetails() default: cmd.log.Error("Invalid command") } diff --git a/core/peer.go b/core/peer.go index 553cd878..fb9e9cf6 100644 --- a/core/peer.go +++ b/core/peer.go @@ -7,6 +7,7 @@ import ( "github.com/rubixchain/rubixgoplatform/core/ipfsport" "github.com/rubixchain/rubixgoplatform/core/model" + "github.com/rubixchain/rubixgoplatform/core/wallet" "github.com/rubixchain/rubixgoplatform/util" "github.com/rubixchain/rubixgoplatform/wrapper/ensweb" ) @@ -124,3 +125,12 @@ func (c *Core) connectPeer(peerID string) (*ipfsport.Peer, error) { // TODO:: Valid the peer version before proceesing return p, nil } + +func (c *Core) AddPeerDetails(peer_detail wallet.DIDPeerMap) error { + err := c.w.AddDIDPeerMap(peer_detail.DID, peer_detail.PeerID, *peer_detail.DIDType) + if err != nil { + c.log.Error("Failed to add PeerDetails to DIDPeerTable", "err", err) + return err + } + return nil +} diff --git a/docs/docs.go b/docs/docs.go index 41029507..973f307b 100644 --- a/docs/docs.go +++ b/docs/docs.go @@ -1,5 +1,4 @@ -// Code generated by swaggo/swag. DO NOT EDIT. - +// Package docs Code generated by swaggo/swag. DO NOT EDIT package docs import "github.com/swaggo/swag" @@ -19,6 +18,40 @@ const docTemplate = `{ "host": "{{.Host}}", "basePath": "{{.BasePath}}", "paths": { + "/api/add-peer-details": { + "post": { + "description": "This API allows the user to add peer details manually", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "Account" + ], + "summary": "Add Peer", + "parameters": [ + { + "description": "Peer Details", + "name": "input", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/server.DIDPeerMapTemp" + } + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/model.BasicResponse" + } + } + } + } + }, "/api/addnftsale": { "post": { "description": "This API will put NFTs for sale", @@ -866,6 +899,20 @@ const docTemplate = `{ } } }, + "server.DIDPeerMapTemp": { + "type": "object", + "properties": { + "did": { + "type": "string" + }, + "didtype": { + "type": "integer" + }, + "peerID": { + "type": "string" + } + } + }, "server.DeploySmartContractSwaggoInput": { "type": "object", "properties": { diff --git a/docs/swagger.json b/docs/swagger.json index dabd60e7..95143433 100644 --- a/docs/swagger.json +++ b/docs/swagger.json @@ -10,6 +10,40 @@ "version": "0.9" }, "paths": { + "/api/add-peer-details": { + "post": { + "description": "This API allows the user to add peer details manually", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "Account" + ], + "summary": "Add Peer", + "parameters": [ + { + "description": "Peer Details", + "name": "input", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/server.DIDPeerMapTemp" + } + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/model.BasicResponse" + } + } + } + } + }, "/api/addnftsale": { "post": { "description": "This API will put NFTs for sale", @@ -857,6 +891,20 @@ } } }, + "server.DIDPeerMapTemp": { + "type": "object", + "properties": { + "did": { + "type": "string" + }, + "didtype": { + "type": "integer" + }, + "peerID": { + "type": "string" + } + } + }, "server.DeploySmartContractSwaggoInput": { "type": "object", "properties": { diff --git a/docs/swagger.yaml b/docs/swagger.yaml index f5e2f795..17ba1455 100644 --- a/docs/swagger.yaml +++ b/docs/swagger.yaml @@ -56,6 +56,15 @@ definitions: $ref: '#/definitions/wallet.TransactionCount' type: array type: object + server.DIDPeerMapTemp: + properties: + did: + type: string + didtype: + type: integer + peerID: + type: string + type: object server.DeploySmartContractSwaggoInput: properties: comment: @@ -145,6 +154,28 @@ info: title: Rubix Core version: "0.9" paths: + /api/add-peer-details: + post: + consumes: + - application/json + description: This API allows the user to add peer details manually + parameters: + - description: Peer Details + in: body + name: input + required: true + schema: + $ref: '#/definitions/server.DIDPeerMapTemp' + produces: + - application/json + responses: + "200": + description: OK + schema: + $ref: '#/definitions/model.BasicResponse' + summary: Add Peer + tags: + - Account /api/addnftsale: post: consumes: diff --git a/server/addpeer.go b/server/addpeer.go new file mode 100644 index 00000000..62d83357 --- /dev/null +++ b/server/addpeer.go @@ -0,0 +1,49 @@ +package server + +import ( + "strings" + + "github.com/rubixchain/rubixgoplatform/core/wallet" + "github.com/rubixchain/rubixgoplatform/wrapper/ensweb" +) + +type DIDPeerMapTemp struct { + DID string + DIDType int + PeerID string +} + +// APIAddPeerDetails godoc +// @Summary Add Peer +// @Description This API allows the user to add peer details manually +// @Tags Account +// @Accept json +// @Produce json +// @Param input body DIDPeerMapTemp true "Peer Details" +// @Success 200 {object} model.BasicResponse +// @Router /api/add-peer-details [post] +func (s *Server) APIAddPeerDetails(req *ensweb.Request) *ensweb.Result { + var pd DIDPeerMapTemp + var peer_detail wallet.DIDPeerMap + err := s.ParseJSON(req, &pd) + if err != nil { + return s.BasicResponse(req, false, "invalid input request", nil) + } + if pd.DIDType < 0 || pd.DIDType > 4 { + return s.BasicResponse(req, false, "Invalid DID Type", nil) + } + if !strings.HasPrefix(pd.PeerID, "12D3KooW") || len(pd.PeerID) < 52 { + return s.BasicResponse(req, false, "Invalid Peer ID", nil) + } + if !strings.HasPrefix(pd.DID, "bafybmi") || len(pd.DID) < 59 { + return s.BasicResponse(req, false, "Invalid DID", nil) + } + peer_detail.DID = pd.DID + peer_detail.PeerID = pd.PeerID + peer_detail.DIDType = &pd.DIDType + err = s.c.AddPeerDetails(peer_detail) + if err != nil { + return s.BasicResponse(req, false, "Failed to add peers in DB, "+err.Error(), nil) + } + return s.BasicResponse(req, true, "Peers added successfully", nil) +} diff --git a/server/server.go b/server/server.go index e831a91b..b58ec082 100644 --- a/server/server.go +++ b/server/server.go @@ -156,10 +156,10 @@ func (s *Server) RegisterRoutes() { s.AddRoute(setup.APIRemoveTokenChainBlock, "POST", s.AuthHandle(s.APIRemoveTokenChainBlock, true, s.AuthError, false)) s.AddRoute(setup.APIReleaseAllLockedTokens, "GET", s.AuthHandle(s.APIReleaseAllLockedTokens, true, s.AuthError, false)) s.AddRoute(setup.APICheckQuorumStatus, "GET", s.AuthHandle(s.APICheckQuorumStatus, false, s.AuthError, false)) - s.AddRoute(setup.APIGetAllExplorer, "GET", s.AuthHandle(s.APIGetAllExplorer, false, s.AuthError, true)) s.AddRoute(setup.APIAddExplorer, "POST", s.AuthHandle(s.APIAddExplorer, false, s.AuthError, true)) s.AddRoute(setup.APIRemoveExplorer, "POST", s.AuthHandle(s.APIRemoveExplorer, false, s.AuthError, true)) + s.AddRoute(setup.APIAddPeerDetails, "POST", s.AuthHandle(s.APIAddPeerDetails, false, s.AuthError, true)) } func (s *Server) ExitFunc() error { diff --git a/setup/setup.go b/setup/setup.go index 27fe74df..09bb64a1 100644 --- a/setup/setup.go +++ b/setup/setup.go @@ -66,6 +66,7 @@ const ( APIGetAllExplorer string = "/api/get-all-explorer" APIAddExplorer string = "/api/add-explorer" APIRemoveExplorer string = "/api/remove-explorer" + APIAddPeerDetails string = "/api/add-peer-details" ) // jwt.RegisteredClaims From d6358548ed5a50c1201f0d4f2e525e3bb1a2fa03 Mon Sep 17 00:00:00 2001 From: Arnab Ghose Date: Thu, 11 Apr 2024 14:32:55 +0530 Subject: [PATCH 023/129] feat: added API endpoint and CLI command to fetch a node's peer ID --- client/node.go | 9 +++++++++ command/command.go | 7 ++++++- command/node.go | 17 +++++++++++++++++ server/node.go | 9 +++++++++ server/server.go | 1 + setup/setup.go | 1 + 6 files changed, 43 insertions(+), 1 deletion(-) create mode 100644 server/node.go diff --git a/client/node.go b/client/node.go index 02604409..0ef5334d 100644 --- a/client/node.go +++ b/client/node.go @@ -13,3 +13,12 @@ func (c *Client) Shutdown() (string, bool) { } return rm.Message, rm.Status } + +func (c *Client) PeerID() (string, bool) { + var rm model.BasicResponse + err := c.sendJSONRequest("GET", setup.APIPeerID, nil, nil, &rm) + if err != nil { + return "Failed to fetch peer ID of node, error: " + err.Error(), false + } + return rm.Message, rm.Status +} diff --git a/command/command.go b/command/command.go index 9f68eb3e..2e292827 100644 --- a/command/command.go +++ b/command/command.go @@ -76,6 +76,7 @@ const ( DumpSmartContractTokenChainCmd string = "dumpsmartcontracttokenchain" GetTokenBlock string = "gettokenblock" GetSmartContractData string = "getsmartcontractdata" + GetPeerID string = "get-peer-id" ReleaseAllLockedTokensCmd string = "releaseAllLockedTokens" CheckQuorumStatusCmd string = "checkQuorumStatus" AddExplorerCmd string = "addexplorer" @@ -125,6 +126,7 @@ var commands = []string{VersionCmd, DumpSmartContractTokenChainCmd, GetTokenBlock, GetSmartContractData, + GetPeerID, CheckQuorumStatusCmd, } var commandsHelp = []string{"To get tool version", @@ -168,7 +170,8 @@ var commandsHelp = []string{"To get tool version", "This command will subscribe to a smart contract token", "This command will dump the smartcontract token chain", "This command gets token block", - "This command gets the smartcontract data from latest block"} + "This command gets the smartcontract data from latest block", + "This command will fetch the peer ID of the node"} type Command struct { cfg config.Config @@ -587,6 +590,8 @@ func Run(args []string) { cmd.getSmartContractData() case ExecuteSmartcontractCmd: cmd.executeSmartcontract() + case GetPeerID: + cmd.peerIDCmd() case ReleaseAllLockedTokensCmd: cmd.releaseAllLockedTokens() case CheckQuorumStatusCmd: diff --git a/command/node.go b/command/node.go index 87975cac..e343eb34 100644 --- a/command/node.go +++ b/command/node.go @@ -1,5 +1,10 @@ package command +import ( + "fmt" + "os" +) + func (cmd *Command) ShutDownCmd() { msg, status := cmd.c.Shutdown() if !status { @@ -8,3 +13,15 @@ func (cmd *Command) ShutDownCmd() { } cmd.log.Info("Shutdown initiated successfully, " + msg) } + +func (cmd *Command) peerIDCmd() { + msg, status := cmd.c.PeerID() + if !status { + cmd.log.Error("Failed to fetch peer ID of the node", "msg", msg) + return + } + _, err := fmt.Fprint(os.Stdout, msg, "\n") + if err != nil { + cmd.log.Error(err.Error()) + } +} diff --git a/server/node.go b/server/node.go new file mode 100644 index 00000000..37ccf3ed --- /dev/null +++ b/server/node.go @@ -0,0 +1,9 @@ +package server + +import ( + "github.com/rubixchain/rubixgoplatform/wrapper/ensweb" +) + +func (s *Server) APIPeerID(req *ensweb.Request) *ensweb.Result { + return s.BasicResponse(req, true, s.c.GetPeerID(), nil) +} diff --git a/server/server.go b/server/server.go index e831a91b..b16b6ef1 100644 --- a/server/server.go +++ b/server/server.go @@ -154,6 +154,7 @@ func (s *Server) RegisterRoutes() { s.AddRoute(setup.APIRegisterCallBackURL, "POST", s.AuthHandle(s.APIRegisterCallbackURL, true, s.AuthError, false)) s.AddRoute(setup.APIGetTxnByNode, "GET", s.AuthHandle(s.APIGetTxnByNode, true, s.AuthError, false)) s.AddRoute(setup.APIRemoveTokenChainBlock, "POST", s.AuthHandle(s.APIRemoveTokenChainBlock, true, s.AuthError, false)) + s.AddRoute(setup.APIPeerID, "GET", s.AuthHandle(s.APIPeerID, false, s.AuthError, false)) s.AddRoute(setup.APIReleaseAllLockedTokens, "GET", s.AuthHandle(s.APIReleaseAllLockedTokens, true, s.AuthError, false)) s.AddRoute(setup.APICheckQuorumStatus, "GET", s.AuthHandle(s.APICheckQuorumStatus, false, s.AuthError, false)) diff --git a/setup/setup.go b/setup/setup.go index 27fe74df..5aa8b15d 100644 --- a/setup/setup.go +++ b/setup/setup.go @@ -61,6 +61,7 @@ const ( APIRegisterCallBackURL string = "/api/register-callback-url" APIGetTxnByNode string = "/api/get-by-node" APIRemoveTokenChainBlock string = "/api/remove-token-chain-block" + APIPeerID string = "/api/get-peer-id" APIReleaseAllLockedTokens string = "/api/release-all-locked-tokens" APICheckQuorumStatus string = "/api/check-quorum-status" APIGetAllExplorer string = "/api/get-all-explorer" From 2d02d7743787d174b4a394951f8d48c06aed9eae Mon Sep 17 00:00:00 2001 From: Arnab Ghose Date: Tue, 7 May 2024 18:50:04 +0530 Subject: [PATCH 024/129] feat: added python tests for RBT transfer --- tests/README.md | 57 +++++++++++ tests/fixtures/didimage.png.file | Bin 0 -> 5276 bytes tests/fixtures/testswarm.key | 3 + tests/helper/__init__.py | 0 tests/helper/utils.py | 16 +++ tests/node/__init__.py | 0 tests/node/actions.py | 111 ++++++++++++++++++++ tests/node/commands.py | 142 ++++++++++++++++++++++++++ tests/node/quorum.py | 67 ++++++++++++ tests/node/utils.py | 16 +++ tests/node/vars.py | 2 + tests/run.py | 169 +++++++++++++++++++++++++++++++ tests/scenarios/__init__.py | 0 tests/scenarios/rbt_transfer.py | 84 +++++++++++++++ tests/shutdown.py | 16 +++ 15 files changed, 683 insertions(+) create mode 100644 tests/README.md create mode 100644 tests/fixtures/didimage.png.file create mode 100644 tests/fixtures/testswarm.key create mode 100644 tests/helper/__init__.py create mode 100644 tests/helper/utils.py create mode 100644 tests/node/__init__.py create mode 100644 tests/node/actions.py create mode 100644 tests/node/commands.py create mode 100644 tests/node/quorum.py create mode 100644 tests/node/utils.py create mode 100644 tests/node/vars.py create mode 100644 tests/run.py create mode 100644 tests/scenarios/__init__.py create mode 100644 tests/scenarios/rbt_transfer.py create mode 100644 tests/shutdown.py diff --git a/tests/README.md b/tests/README.md new file mode 100644 index 00000000..496afa0c --- /dev/null +++ b/tests/README.md @@ -0,0 +1,57 @@ +# Test Scripts + +The test script does the complete setup by building the rubix node based on the Operatng System, downloads IPFS binary for a specific version (refer `IPFS_KUBO_VERSION` variable in `run.py`) and sets up quorum and non-quorum nodes before proceeding with running all the test cases. + +The test script covers the following RBT Transfer scenarios: + +1. Shuttle Transfer (Success Case)
+ 1.1 Generate 2 whole RBT for A
+ 1.2 Transfer 0.5 from A to B
+ 1.3 Transfer 1.499 from A to B
+ 1.4 (Transfer 0.25 from B to A) * 4
+ 1.5 Transfer 1 RBT from A to B
+ 1.6 Generate 2 whole RBT for A
+ 1.7 Transfer 2 RBT from A to B
+ 1.8 Transfer 0.001 from A to B
+ +2. Insufficient Balance Transfer (Failure Case)
+ 2.1 Transferring 100 RBT from A which has zero balance
+ 2.2 Transferring 100 RBT from B which has insufficient balance
+ +3. Transferring 0.00000009 RBT from B which is more than allowed decimal places (Failure Case) + +## Prerequisites + +- Python 3.10+ ([Install Ref](https://www.python.org/downloads/)) +- `pip` package manger ([Install Ref](https://pip.pypa.io/en/stable/installation/)) +- `requests` package. After installing Python and pip, run `pip install requests` to install this package + +## Running the tests + +To start the test. Please NOTE that it must be run from the `tests` directory only. + +``` +python3 run.py +``` + +### Flags + +The test script is equipped with CLI Parser. Following are the flags and their description + +``` +usage: run.py [-h] [--skip_prerequisite | --no-skip_prerequisite] [--run_nodes_only | --no-run_nodes_only] [--skip_adding_quorums | --no-skip_adding_quorums] + [--run_tests_only | --no-run_tests_only] + +CLI to run tests for Rubix + +options: + -h, --help show this help message and exit + --skip_prerequisite, --no-skip_prerequisite + skip prerequisite steps such as installing IPFS and building Rubix + --run_nodes_only, --no-run_nodes_only + only run the rubix nodes and skip the setup + --skip_adding_quorums, --no-skip_adding_quorums + skips adding quorums + --run_tests_only, --no-run_tests_only + only proceed with running tests +``` \ No newline at end of file diff --git a/tests/fixtures/didimage.png.file b/tests/fixtures/didimage.png.file new file mode 100644 index 0000000000000000000000000000000000000000..09bf52e0a3e9f0188c6c68b274457a90856352f8 GIT binary patch literal 5276 zcmX9?c_7s96MlCc+mc(k$(1AWQ$)FoT)9)I*r*7(Z(>ndB|2QW>Wg)h(1n~ULWEpd zv@DWqWpl3k_ip{Q`No%fx2k9j8E(%g`ZMUVvmz-DZuZw&wf{zZU&%<$*3U(pQ! zcwLP3_0ET6Es*qZq`|<}KV|K_@4ua9J#gc{d&X9Jtctvrx(I=S{~Ac>>AmDStpn%7<_-efYDyaz8nm#Tj?#9!oBFpZ5J1@4lUWVDF|( zeXG9Q?Y0}Xyt}tPy0^12-t=!l_Bb4`JDLc*WE>5TMLh{a zNT3xF4NQsjPZnTZeVb5*T_&8K_^@J*&~2_|j6hQ?>K#idz=oC<AOYD-L!OyF_QTLm;P&>!w7m9hk!&(2-=3ki5DOP3b#)&G^6 z&CntFLgIfRzwaEOE2|H@{Hsjj{0rHxQld+Lbp#r}0Ec=x(&$p7s2_iQ@A%o$edmwo z(jmq&p>&%k7kcT#HpfZPO>ts%Y4mBU@;tz)J zzqhvbQ1ysiR28~J#vzSXE~d^H!D`32oAujz(m*)7-Gh3N%7e-4;JZSof75ZL-mTRO z`HIkRYxhH+H@51X7|nxxmBQoWG(1)HhkI=&1X)EIctDSI8NxeYHO4;(RmHN+nksFi zZI0BD=#uf155^W^yK6$;xM^W;6HbzY2?xl!!&62mb7TWbThDv<#3_wZDcHBQj0igoDitcZav{O3UD|m@JnG+D)zfJW&kZseZV3XM0Hk98=$w~tS zjLsvJjZ!|aZ5-OEe4k9>cxy=Bq8RI3JNJ9@+?bh-gaVndsB9!5))CnSS7>vjXm+{> zoBCJgmi8@lty)^;`j@)lgK*q)b#DBI}_E#mr_!GH~A+jgfyP=5Rthu6nD4;}f$ zn9n_>~G!KUvI`w$8yLNnpda&dk{CMb_MFx;j{Pvbc$m6#r&5=wMY= z7?+kE*yYg>o*Gai1V3Bo^AX5=Iz3cKxOr;3zu|ctH`#-HlRVkadUIT)J!ENtyMAnY zJ|K%lLnSS_q3aAN%3`iJslzd|5(Q{k8WXP6=MS@)y$T$gh1q6`I>wr9KvC}I0)#(W zUL$iUbo`-+;T|iRzv??0#bbd07`708R^}W(u_hvWwCljyi|MltcosX;_(5fJFEbrJxu`35 z02mgf4A0ZFd#czqWAfD66PVSFH|BF0LHV&mpJYCXQ{KNATxfhsd~KAYh4=wumRM!7 zF)zUc%I}doiurmz`9|avY2dVmDMRzkZrdk(;Vv+MF}M`VmD3i^>@?yrV5ihQ^+lE3 z+5cdM01Ba3crt>FW|sROxQ%P3`h`;w^<}y>ck#PDAI+g_W-J?}s(igkoRuiFXfzR6 z8}nRO#U!w|JN#*I7AJ)F1MsE-r6Wm79r4{>#2b2Vvh9PBH(&>tBz8mEPooc7Az+U~ z!N7a-E}UyFJXPWng*HmLcVq2%O3Tz-0;8u#bLvM`B-D0J7i&!^B|!A-x9?Ru*x z5?4ATrph`LfhT4!R$|-d%70s5YPPKUyhWL>!5K~+1ccmW$!4PHHsgGM@YVHS^P!>_ z1mDc2!NZj10zi23iZa;|=FzUXYhOT5aa7z2DzPR0`%1?#IIJpsybH4y^cLT3=c(>6 zUxWFbf|s85CwKG3)MvYi&3QDj`2)qXX@PLGZ~$JNjCvf#rI_`pi(=u-HTDj5$h@x% zm)uYavwnf)vPB*4U?j8V=u-FD^eHj?tlEo5P?roiZ-rCs9_Xx}sCV5kyt#QG1#Y7% z(OL`C8;`PeyrWU9Dp}l9%_Z5!?giCdq^5c#oIrZGm!11jUJ+n#yYHgv=Wmp&b)O+* z59{b8Fe!IGy)7z!mgH1xZGzo;jkG9q)Mw4BK&_8Qm0V0Ncy0-+k*fP7^+}R)h4s!p zxHgrYYc}!HgdOet+k;y8!DyY&>*|Y{b~0M+SH<)Y7&WRiNhjGRqsFe!yRZPSZtIS= z{1|tOgPprf^6lL2*}4q|c`cxu<&G+V_hUNv zi2C9;rw=RVR3t0IYcgCcQ&D!3B>jD|?kz(K;BX-1lrKj-H8&9=8tV+~2v{;xU$Bwo zSZ=H5GpX(z%iWK0eL(Q0?o{0x>tE?eKoUaYuuhX(l-o`Ly-H`~5iK?GB7Q?gb&r~% zIvJ_^&VyJ~WIdbj)WQpfLxYzu#zT2}7+6rmbWc2ocA_wICz-HcD2)YwLh1u6kGO9h z&_!VUw%#o0bzk)9G)Y=Ncv=hlh16pHX=?LJQGt^lFDUS5&`?aDTziob$z+B8U#33+ zzKOYKAoMH(6O@K^wN}byfL})NimLI!3HF>)ZlMI`e` zRce^Hjb&dMMjlZe$XgSn(B2m-#x;qwc*b)bkT&o04<_11riCG%q#||Ky||`ZhSacz z@ILRgLVtU0;E8Rso(MeWEJ8b?f_!b%4yt*^m%6Oh!1MolTn((jOxFm(Z_eP{O)iZN zPJF1Gh!vP=ks}ZFKS=KpSBUNDG-9%Xb25A*bT7Ej(a3O=DF;5KvvEj*=fUW)Cu5%2 zcLexwKiaSX>7&RKA~SAtcfUq^?aAE<1AR66Io^@PYS9JDxw~xwj;40 zQ`G##Qoz$oEnQn_y^4D*H0=zYN7C29(;+em%(_B_#Ti z%UQq@@Oz_cnB1Hu0z>>+S&_juO8PhQL!MYQ^ou@+ z7QsC3bR@y840Flp*r)&*4_7!_jH14nBy!o|D;IV+X)3D{*Zf$(hzKDgGTcT7&T)ibLMz=Y)nwKc@CyIE;mk8axiue!H z(R*k8nMg-YG7ulA?ywg)w(+ZB6+(Yw!FA#|y_Zr9D6S9OWy#hJVjZ{@;m?v1P|qTXH~$j?j2R;SyKs z08SDna;x0XPOHJ*3sbrDepQvquiUjyGcmi8(-0PLT&2Gqo7}g;&7#VG`A__qT4$zS zn=|-PNPC-~417e#t}OeSHJmug;2l_*^|2Z$Y+8piGkn9r+-*O8IfWDCFm~Y`^<$^` z$5uQhua|VKl~xB)bm#7Rh6&e@KeUZ2eMDg;X$}1ox2rXjgERPf!e61{YBhsy0}bA_ zb8~lB6sJKsPIX6fFw{xezOU?yR!I`)IJr|#frsiRd|U0rL`l(;LxaFlb!V**#@4p4 zY@U5LyL0fN&shvplt0r0d9)uJ@OC+Kr0%8pa_78R80&~=g3o``0^6%@_vPq?u`AXU zp7%z3g`MYx^Y3*mlZQjeaE<-ER@^@ig2V|Wd`WoJ@&?AaHPZud*-T`Im@MM=;?>!Pi^~wSv1!5S;<9$?Xf>B z#mtyf3n;i;ip*IZTJd;$uagT`t`)*Q((_0D!IMLNfS9z$)h`EOURR&#-Z8`}jc;^it!3594ByWJi1I(Fo7v&qqLQ;E8I}~&U@LUHqp3B z0bPs2PTI9k+rKYxdg{^4fBg4GGh&8daD8>k0HR))$ zL$X(vg-NjT7!KhQlAR#2P|e|0+Gt=*Rs|8b#mVObE2K8Km2)Io(*L+p)h?F5&XbuM3StO!#?*D_-3Xx^Ko!!4p4wU=ANkfXMP ziJ`mp?!A|c$>QLAab{YFgrOXMcJQYQh1+^Dk+Vh^n`1&}xjymlWnM-C&F9qlO5Y6l zSRYRFDUT!dGLgrEX?0CBF*y{K?R&yb^*rCGsxZ4#Q`Dp)J~-a@SgFN8eooPqb=>c( zJB6iQPnaW;LC$OI8+~QQsyAwvEu@BeE}I~ku-Pf2aDOG5@z-aEiQkCw_xmj zDYwhlki>$ckoi{>&8pR?z1d>UkFuc~oHc9sopl(-`?A@2I3~a9PPGl2(L?G!-%^xTs^AXl8}ahywe$)D?Ln$SH4lpXlq<4TE4;NE(C_lZ_uen(FdY;%Mdn!(}>2qhp+4P=8(iP8|z*dW$t*LaxOs80% z0R?qYU}QzmX1DqWl3)l$L$;pngYvMfl?I+5DsEsqY`L|9C4x^#MZU8oXd@He zCiN{6V>)<8T)?jrspzcFk%a5-O z)UaZRG3H$X)rWq;C{ynSwr#EI`xT^W=qp?y>uIn(YRcr_IMNj%WTpT=# zRO6!eFF?|6nPRZYl&c^k( z)59Tg=7wD%N64zL1Bsifu#SiAto*)z3aN*5zIO~fj+Fj~*nFxvRc3>REhos>=!y+L zxKfDtnpBhAU@nbqi>QL^KN*1w=zx`fA#6^GtV2r^@Yw4PYym*U*Td)kDvs6p{8P-{ z`G+`nIN%?`k@j~eBMtlf?Z9@R-_ik7V*@yc?1TOxdfxs+c+%Mg^zl}D>n{Q)2N{nI s^CA2Z28D8<^{tp2o!dA0RRAK>z>% literal 0 HcmV?d00001 diff --git a/tests/fixtures/testswarm.key b/tests/fixtures/testswarm.key new file mode 100644 index 00000000..8985c5d0 --- /dev/null +++ b/tests/fixtures/testswarm.key @@ -0,0 +1,3 @@ +/key/swarm/psk/1.0.0/ +/base16/ +278b9a199c43fa84178920bd9f5cbcd69e933ddf02a8f69e47a3ea5a1705512f \ No newline at end of file diff --git a/tests/helper/__init__.py b/tests/helper/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/tests/helper/utils.py b/tests/helper/utils.py new file mode 100644 index 00000000..8011a780 --- /dev/null +++ b/tests/helper/utils.py @@ -0,0 +1,16 @@ +def expect_success(func): + def wrapper(*args, **kwargs): + try: + func(*args, **kwargs) + except: + raise Exception("The action was expected to pass, but it failed") + return wrapper + +def expect_failure(func): + def wrapper(*args, **kwargs): + try: + func(*args, **kwargs) + raise Exception("The action was expected to fail, but it passed") + except: + return 0 + return wrapper \ No newline at end of file diff --git a/tests/node/__init__.py b/tests/node/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/tests/node/actions.py b/tests/node/actions.py new file mode 100644 index 00000000..7251f265 --- /dev/null +++ b/tests/node/actions.py @@ -0,0 +1,111 @@ +from .commands import cmd_run_rubix_servers, cmd_get_peer_id, cmd_create_did, cmd_register_did, \ + cmd_generate_rbt, cmd_add_quorum_dids, cmd_setup_quorum_dids, cmd_rbt_transfer +from .utils import get_node_name_from_idx, save_to_json + +def add_quorums(node_config: dict): + for config in node_config.values(): + cmd_add_quorum_dids( + config["server"], + config["grpcPort"] + ) + +def setup_quorums(node_config: dict): + for config in node_config.values(): + cmd_setup_quorum_dids( + config["did"], + config["server"], + config["grpcPort"] + ) + +def quorum_config(node_config: dict, skip_adding_quorums: bool = False, create_quorum_list: bool = False): + # Prepare quorumlist.json + quorum_list = [] + if create_quorum_list: + for config in node_config.values(): + quorum_info = { + "type": 2, + "address": config["peerId"] + "." + config["did"] + } + + quorum_list_file_path = "../linux/quorumlist.json" # TODO: make it Dynamic + quorum_list.append(quorum_info) + + save_to_json(quorum_list_file_path, quorum_list) + + # # add quorums + if not skip_adding_quorums: + add_quorums(node_config) + + setup_quorums(node_config) + + +def get_base_ports(): + base_ens_server = 20000 + base_grpc_port = 10500 + + return base_ens_server, base_grpc_port + +def setup_rubix_nodes(node_count: int = 0, node_prefix_str: str = "node"): + base_ens_server, base_grpc_port = get_base_ports() + + node_config = {} + + # Start rubix servers + loop_start_idx, loop_end_idx = 0, node_count + + for i in range(loop_start_idx, loop_end_idx): + k = i if node_prefix_str == "node" else (10+i) + + ens_server = base_ens_server + k + print(f"Running server at port: {ens_server}") + grpc_port = base_grpc_port + k + + node_name = get_node_name_from_idx(k, node_prefix_str) + + cmd_run_rubix_servers(node_name, k, grpc_port) + + node_config[node_name] = { + "did": "", + "server": ens_server, + "grpcPort": grpc_port, + "peerId": "" + } + + return node_config + + +def fetch_peer_ids(node_config: dict): + print("Fetching Node IDs........") + for config in node_config.values(): + peer_id = cmd_get_peer_id(config["server"], config["grpcPort"]) + config["peerId"] = peer_id + print("Fetched all Node IDs") + + +def create_and_register_did(node_config: dict, register_did: bool = True): + for config in node_config.values(): + did_id = cmd_create_did(config["server"], config["grpcPort"]) + print("Created DID : ", did_id) + + if register_did: + print(f"Registering DID: {did_id}") + cmd_register_did(did_id, config["server"], config["grpcPort"]) + print("DID is registered successfully\n") + + config["did"] = did_id + +def fund_dids_with_rbt(node_config: dict, rbt_amount: int = 30): + for config in node_config.values(): + cmd_generate_rbt(config["did"], rbt_amount, config["server"], config["grpcPort"]) + print("DID ", config["did"], f" is funded with {rbt_amount} RBT") + +def fund_did_with_rbt(config: dict, rbt_amount: int = 30): + output = cmd_generate_rbt(config["did"], rbt_amount, config["server"], config["grpcPort"]) + print(output) + return output + +def rbt_transfer(config_sender: dict, config_receiver: dict, transfer_rbt_amount: int): + sender_address = config_sender["peerId"] + "." + config_sender["did"] + receiver_address = config_receiver["peerId"] + "." + config_receiver["did"] + + cmd_rbt_transfer(sender_address, receiver_address, transfer_rbt_amount, config_sender["server"], config_sender["grpcPort"]) \ No newline at end of file diff --git a/tests/node/commands.py b/tests/node/commands.py new file mode 100644 index 00000000..42c76f24 --- /dev/null +++ b/tests/node/commands.py @@ -0,0 +1,142 @@ +import subprocess +import os +import re + +def run_command(cmd_string, is_output_from_stderr=False): + assert isinstance(cmd_string, str), "command must be of string type" + cmd_result = subprocess.run(cmd_string, stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=True) + code = cmd_result.returncode + + if int(code) != 0: + err_output = cmd_result.stderr.decode('utf-8')[:-1] + print(err_output) + return err_output, int(code) + + output = "" + if not is_output_from_stderr: + output = cmd_result.stdout.decode('utf-8')[:-1] + print(output) + if output.find('[ERROR]') > 0 or output.find('parse error') > 0: + return output, 1 + else: + return output, code + else: + output = cmd_result.stderr.decode('utf-8')[:-1] + if output.find('[ERROR]') > 0 or output.find('parse error') > 0: + return output, 1 + else: + return output, code + +def cmd_run_rubix_servers(node_name, server_port_idx, grpc_port): + os.chdir("../linux") + cmd_string = f"screen -S {node_name} -d -m ./rubixgoplatform run -p {node_name} -n {server_port_idx} -s -testNet -grpcPort {grpc_port}" + _, code = run_command(cmd_string) + if code != 0: + raise Exception("Error occurred while run the command: " + cmd_string) + os.chdir("../tests") + +def cmd_create_did(server_port, grpc_port): + os.chdir("../linux") + cmd_string = f"./rubixgoplatform createdid -port {server_port} -grpcPort {grpc_port}" + output, code = run_command(cmd_string, True) + + if code != 0: + raise Exception("Error occurred while run the command: " + cmd_string) + + did_id = "" + if "successfully" in output: + pattern = r'bafybmi\w+' + matches = re.findall(pattern, output) + if matches: + did_id = matches[0] + else: + raise Exception("unable to extract DID ID") + + os.chdir("../tests") + return did_id + +def cmd_register_did(did_id, server_port, grpc_port): + os.chdir("../linux") + cmd_string = f"./rubixgoplatform registerdid -did {did_id} -port {server_port} -grpcPort {grpc_port}" + output, code = run_command(cmd_string) + print(output) + + if code != 0: + raise Exception("Error occurred while run the command: " + cmd_string) + + os.chdir("../tests") + return output + +def cmd_generate_rbt(did_id, numTokens, server_port, grpc_port): + os.chdir("../linux") + cmd_string = f"./rubixgoplatform generatetestrbt -did {did_id} -numTokens {numTokens} -port {server_port} -grpcPort {grpc_port}" + output, code = run_command(cmd_string, True) + + if code != 0: + raise Exception("Error occurred while run the command: " + cmd_string) + + os.chdir("../tests") + return output + +def cmd_add_quorum_dids(server_port, grpc_port): + os.chdir("../linux") + cmd_string = f"./rubixgoplatform addquorum -port {server_port} -grpcPort {grpc_port}" + output, code = run_command(cmd_string, True) + print(output) + if code != 0: + raise Exception("Error occurred while run the command: " + cmd_string) + + os.chdir("../tests") + return output + +def cmd_shutdown_node(server_port, grpc_port): + os.chdir("../linux") + cmd_string = f"./rubixgoplatform shutdown -port {server_port} -grpcPort {grpc_port}" + output, _ = run_command(cmd_string, True) + print(output) + + os.chdir("../tests") + return output + +def cmd_setup_quorum_dids(did, server_port, grpc_port): + os.chdir("../linux") + cmd_string = f"./rubixgoplatform setupquorum -did {did} -port {server_port} -grpcPort {grpc_port}" + output, code = run_command(cmd_string, True) + print(output) + if code != 0: + raise Exception("Error occurred while run the command: " + cmd_string) + + os.chdir("../tests") + return output + +def cmd_get_peer_id(server_port, grpc_port): + os.chdir("../linux") + cmd_string = f"./rubixgoplatform get-peer-id -port {server_port} -grpcPort {grpc_port}" + output, code = run_command(cmd_string) + + if code != 0: + raise Exception("Error occurred while run the command: " + cmd_string) + os.chdir("../tests") + return output + +def check_account_info(did, server_port, grpc_port): + os.chdir("../linux") + cmd_string = f"./rubixgoplatform getaccountinfo -did {did} -port {server_port} -grpcPort {grpc_port}" + output, code = run_command(cmd_string) + + if code != 0: + raise Exception("Error occurred while run the command: " + cmd_string) + os.chdir("../tests") + return output + +# Note: address != did, address = peerId.didId +def cmd_rbt_transfer(sender_address, receiver_address, rbt_amount, server_port, grpc_port): + os.chdir("../linux") + cmd_string = f"./rubixgoplatform transferrbt -senderAddr {sender_address} -receiverAddr {receiver_address} -rbtAmount {rbt_amount} -port {server_port} -grpcPort {grpc_port}" + output, code = run_command(cmd_string, True) + print(output) + if code != 0: + raise Exception("Error occurred while run the command: " + cmd_string) + + os.chdir("../tests") + return output \ No newline at end of file diff --git a/tests/node/quorum.py b/tests/node/quorum.py new file mode 100644 index 00000000..b8ca59d7 --- /dev/null +++ b/tests/node/quorum.py @@ -0,0 +1,67 @@ +import pprint +import time + +from .actions import setup_rubix_nodes, fetch_peer_ids, create_and_register_did, \ + fund_dids_with_rbt, quorum_config +from .utils import save_to_json + +def run_quorum_nodes(node_config_path, only_run_nodes, skip_adding_quorums): + node_config_path = "./quorum_config.json" + + print("Running Rubix nodes......") + node_config = setup_rubix_nodes(5) + print("Rubix nodes are now running") + + if not only_run_nodes: + print("Waiting 20 seconds before fetching all node peer IDs............") + time.sleep(20) + + fetch_peer_ids(node_config) + + print("Creation and registeration of quorum DIDs have started") + create_and_register_did(node_config) + print("All quorum DIDs have been registered") + + print("Initiating funding of these quorum DIDs") + fund_dids_with_rbt(node_config) + print("All Quorum DIDs have been funded") + + save_to_json(node_config_path, node_config) + + print("Setting up quorums and saving information about them to quorumlist.json") + quorum_config(node_config, skip_adding_quorums=skip_adding_quorums, create_quorum_list=True) + + pprint.pp(node_config) + print("Quorums have been configured. You can proceed with running Test scenarios") + else: + quorum_config(node_config, skip_adding_quorums=True, create_quorum_list=False) + + return node_config + +def run_non_quorum_nodes(node_config_path, only_run_nodes, skip_adding_quorums): + node_config_path = "./non_quorum_config.json" + + print("Running non-quorum nodes...") + node_config = setup_rubix_nodes(2, "nodeNq") + print("Non-quorum nodes are running successfully") + + if not only_run_nodes: + print("Waiting 20 seconds before fetching all node peer IDs............") + time.sleep(20) + fetch_peer_ids(node_config) + + print("Creation of Non Quorum DIDs have started") + create_and_register_did(node_config, False) + print("Non Quorum DIDs have been created") + + save_to_json(node_config_path, node_config) + + print("Adding and setting up quorum config") + quorum_config(node_config, skip_adding_quorums=skip_adding_quorums, create_quorum_list=False) + + pprint.pp(node_config) + print("Non Quorum nodes have been configured") + else: + quorum_config(node_config, skip_adding_quorums=True, create_quorum_list=False) + + return node_config \ No newline at end of file diff --git a/tests/node/utils.py b/tests/node/utils.py new file mode 100644 index 00000000..61bcdbe7 --- /dev/null +++ b/tests/node/utils.py @@ -0,0 +1,16 @@ +import json +import sys +import os +sys.path.insert(1, os.getcwd()) +from .vars import QUORUM_NODES + +def get_node_name_from_idx(idx, prefix_string: str = "node"): + return prefix_string + str(idx) + +def save_to_json(filepath, obj): + # Check if file exists. If yes, then remove it + if os.path.exists(filepath): + os.remove(filepath) + + with open(filepath, 'w') as f: + json.dump(obj, f, indent=4) diff --git a/tests/node/vars.py b/tests/node/vars.py new file mode 100644 index 00000000..7b683fcb --- /dev/null +++ b/tests/node/vars.py @@ -0,0 +1,2 @@ +QUORUM_NODES = 5 + diff --git a/tests/run.py b/tests/run.py new file mode 100644 index 00000000..7e8c091b --- /dev/null +++ b/tests/run.py @@ -0,0 +1,169 @@ +import platform +import os +import shutil +import requests +import argparse +from node.commands import run_command +from node.quorum import run_quorum_nodes, run_non_quorum_nodes +from scenarios.rbt_transfer import * + +IPFS_KUBO_VERSION = "v0.21.0" +QUORUM_CONFIG_FILE = "./quorum_config.json" +NON_QUORUM_CONFIG_FILE = "./non_quorum_config.json" + +def get_os_info(): + os_name = platform.system() + build_folder = "" + + if os_name == "Linux": + build_folder = "linux" + elif os_name == "Windows": + build_folder = "windows" + elif os_name == "Darwin": + build_folder = "mac" + else: + print("Unsupported operating system to build Rubix") + return None, None + + return os_name, build_folder + +def download_ipfs_binary(os_name, version, build_dir): + download_url = "" + + if os_name == "Linux": + download_url = f"https://dist.ipfs.tech/kubo/{version}/kubo_{version}_linux-amd64.tar.gz" + elif os_name == "Windows": + download_url = f"https://dist.ipfs.tech/kubo/{version}/kubo_{version}_windows-amd64.zip" + elif os_name == "Darwin": # MacOS + download_url = f"https://dist.ipfs.tech/kubo/{version}/kubo_{version}_darwin-amd64.tar.gz" + else: + raise ValueError("Unsupported operating system") + + # Download the IPFS binary archive + download_path = f"kubo_{version}_{os_name.lower()}-amd64.tar.gz" if os_name != "Windows" else f"kubo_{version}_{os_name.lower()}-amd64.zip" + print("Downloading IPFS binary...") + response = requests.get(download_url) + with open(download_path, "wb") as f: + f.write(response.content) + print("Download completed.") + + # Extract the archive + print("Extracting IPFS binary...") + if os_name == "Windows": + # For Windows, we need to use the 'zipfile' module to extract + import zipfile + with zipfile.ZipFile(download_path, "r") as zip_ref: + zip_ref.extractall("kubo") + else: + # For Linux and MacOS, we use tar + import tarfile + with tarfile.open(download_path, "r:gz" if os_name != "Darwin" else "r") as tar_ref: + tar_ref.extractall("kubo") + print("Extraction completed.") + + # Check the contents of the kubo directory + print("Contents of kubo directory:") + for item in os.listdir("kubo"): + print(item) + + # Move IPFS binary to the appropriate folder + print("Moving IPFS binary...") + src_file = os.path.join("kubo", "kubo", "ipfs") + dest_dir = os.path.join(build_dir, "ipfs") + if os.path.exists(src_file): + shutil.move(src_file, dest_dir) + print("IPFS binary moved to", dest_dir) + + # Check if the file is present at the destination + dest_file = os.path.join(dest_dir) + if not os.path.exists(dest_file): + raise FileNotFoundError("IPFS binary not found at the destination after move operation.") + else: + raise FileNotFoundError("Installed IPFS binary file does not exist.") + + # Clean up + os.remove(download_path) + shutil.rmtree("kubo") + print("\nIPFS has been installed succesfully.") + +def copy_fixtures_to_build_dir(build_directory): + fixtures_directory = os.path.join("tests", "fixtures") + + # Copy didimage.png.file + image_file_src = os.path.join(fixtures_directory, "didimage.png.file") + image_file_dest = os.path.join(build_directory, "image.png") + shutil.copyfile(image_file_src, image_file_dest) + + if not os.path.exists(image_file_dest): + raise FileNotFoundError(f"Copy operation for didimage.png.file failed. Destination file not found: {image_file_dest}") + + # Copy testswarm.key + swarmkey_src = os.path.join(fixtures_directory, "testswarm.key") + swarmkey_dest = os.path.join(build_directory, "testswarm.key") + shutil.copyfile(swarmkey_src, swarmkey_dest) + + if not os.path.exists(swarmkey_dest): + raise FileNotFoundError(f"Copy operation for testswarm.key failed. Destination file not found: {swarmkey_dest}") + + print("\nimage.png and swarm key have been added to build directory successfully") + +def cli(): + parser = argparse.ArgumentParser(description="CLI to run tests for Rubix") + parser.add_argument("--skip_prerequisite", action=argparse.BooleanOptionalAction, help="skip prerequisite steps such as installing IPFS and building Rubix") + parser.add_argument("--run_nodes_only", action=argparse.BooleanOptionalAction, help="only run the rubix nodes and skip the setup") + parser.add_argument("--skip_adding_quorums", action=argparse.BooleanOptionalAction, help="skips adding quorums") + parser.add_argument("--run_tests_only", action=argparse.BooleanOptionalAction, help="only proceed with running tests") + return parser.parse_args() + + +if __name__=='__main__': + os.chdir("../") + + args = cli() + skip_prerequisite = args.skip_prerequisite + run_nodes_only = args.run_nodes_only + skip_adding_quorums = args.skip_adding_quorums + run_tests_only = args.run_tests_only + + non_quorum_node_config = {} + + if not run_tests_only: + os_name, build_folder = get_os_info() + if os_name is None: + exit(1) + + if not skip_prerequisite: + print(f"Building Rubix binary for {os_name}\n") + build_command = "" + if os_name == "Linux": + build_command = "make compile-linux" + elif os_name == "Windows": + build_command = "make compile-windows" + elif os_name == "Darwin": + build_command = "make compile-mac" + + output, code = run_command(build_command) + if code != 0: + print("build failed with error:", output) + exit(1) + else: + print("\nBuild successful\n") + + + download_ipfs_binary(os_name, IPFS_KUBO_VERSION, build_folder) + copy_fixtures_to_build_dir(build_folder) + os.chdir("./tests") + + run_quorum_nodes(QUORUM_CONFIG_FILE, run_nodes_only, skip_adding_quorums=skip_adding_quorums) + + non_quorum_node_config = run_non_quorum_nodes(NON_QUORUM_CONFIG_FILE, run_nodes_only, skip_adding_quorums=skip_adding_quorums) + + # Run RBT Transfer related tests + rbt_transfer_test_list = [ + shuttle_transfer, + insufficient_balance_transfer, + max_decimal_place_transfer + ] + for testFn in rbt_transfer_test_list: + testFn(non_quorum_node_config) + diff --git a/tests/scenarios/__init__.py b/tests/scenarios/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/tests/scenarios/rbt_transfer.py b/tests/scenarios/rbt_transfer.py new file mode 100644 index 00000000..78454198 --- /dev/null +++ b/tests/scenarios/rbt_transfer.py @@ -0,0 +1,84 @@ +from node.actions import rbt_transfer, fund_did_with_rbt +from helper.utils import expect_failure, expect_success + +def max_decimal_place_transfer(config): + node_A_info = config["nodeNq10"] + node_B_info = config["nodeNq11"] + + print("------ Test Case (FAIL) : Transferring 0.00000009 RBT from B which is more than allowed decimal places ------") + + print("\nTransferring 0.00000009 RBT from B to A....") + expect_failure(rbt_transfer)(node_B_info, node_A_info, 0.00000009) + + print("\n------ Test Case (FAIL) : Transferring 0.00000009 RBT from B which is more than allowed decimal places completed ------\n") + +def insufficient_balance_transfer(config): + node_A_info = config["nodeNq10"] + node_B_info = config["nodeNq11"] + + print("\n------ Test Case (FAIL) : Transferring 100 RBT from A which has zero balance ------") + + print("\nTransferring 100 RBT from A to B....") + expect_failure(rbt_transfer)(node_A_info, node_B_info, 100) + + print("\n------ Test Case (FAIL) : Transferring 100 RBT from A which has zero balance completed ------\n") + + + print("\n------ Test Case (FAIL) : Transferring 100 RBT from B which has insufficient balance ------") + + print("\nTransferring 100 RBT from B to A....") + expect_failure(rbt_transfer)(node_B_info, node_A_info, 100) + + print("\n------ Test Case (FAIL) : Transferring 100 RBT from B which has insufficient balance completed ------\n") + +def shuttle_transfer(config): + node_A_info = config["nodeNq10"] + node_B_info = config["nodeNq11"] + + print("------ Test Case (PASS): Shuttle transfer started ------\n") + + print("\n1. Generating 2 whole RBT for A") + expect_success(fund_did_with_rbt)(node_A_info, 2) + print("Funded node A with 2 RBT") + + print("\n2. Transferring 0.5 RBT from A to B....") + expect_success(rbt_transfer)(node_A_info, node_B_info, 0.5) + print("Transferred 0.5 RBT from A to B") + + print("\n3. Transferring 1.499 RBT from A to B....") + expect_success(rbt_transfer)(node_A_info, node_B_info, 1.499) + print("Transferred 1.499 RBT from A to B") + + print("\n4. Transferring 0.25 RBT from B to A....") + expect_success(rbt_transfer)(node_B_info, node_A_info, 0.25) + print("Transferred 0.25 RBT from B to A") + + print("\n5. Transferring 0.25 RBT from B to A....") + expect_success(rbt_transfer)(node_B_info, node_A_info, 0.25) + print("Transferred 0.25 RBT from B to A") + + print("\n6. Transferring 0.25 RBT from B to A....") + expect_success(rbt_transfer)(node_B_info, node_A_info, 0.25) + print("Transferred 0.25 RBT from B to A") + + print("\n7. Transferring 0.25 RBT from B to A....") + expect_success(rbt_transfer)(node_B_info, node_A_info, 0.25) + print("Transferred 0.25 RBT from B to A") + + print("\n8. Transferring 1 RBT from A to B....") + expect_success(rbt_transfer)(node_A_info, node_B_info, 1) + print("Transferred 1 RBT from A to B") + + print("\n9. Generating 2 whole RBT for A") + expect_success(fund_did_with_rbt)(node_A_info, 2) + print("Funded node A with 2 RBT") + + print("\n10. Transferring 2 RBT from A to B....") + expect_success(rbt_transfer)(node_A_info, node_B_info, 2) + print("Transferred 2 RBT from A to B") + + print("\n11. Transferring 0.001 RBT from A to B....") + expect_success(rbt_transfer)(node_A_info, node_B_info, 0.001) + print("Transferred 0.001 RBT from A to B") + + print("\n------ Test Case (PASS): Shuttle transfer completed ------\n") diff --git a/tests/shutdown.py b/tests/shutdown.py new file mode 100644 index 00000000..05c6a090 --- /dev/null +++ b/tests/shutdown.py @@ -0,0 +1,16 @@ +from node.commands import cmd_shutdown_node +from node.actions import get_base_ports + +quorum_base_server, quorum_grpc_server = get_base_ports() + +for i in range(0, 5): + server_port = quorum_base_server + i + grpc_port = quorum_grpc_server + i + + cmd_shutdown_node(server_port, grpc_port) + +for i in range(0, 2): + server_port = quorum_base_server + 10 + i + grpc_port = quorum_grpc_server + 10 + i + + cmd_shutdown_node(server_port, grpc_port) From bb850f6cb44f6c98316e445b993fa8ada511f566 Mon Sep 17 00:00:00 2001 From: Arnab Ghose Date: Wed, 8 May 2024 11:48:06 +0530 Subject: [PATCH 025/129] added func to get the build dir based on the target OS --- tests/README.md | 1 + tests/node/commands.py | 35 ++++++++++++++++++++++++----------- 2 files changed, 25 insertions(+), 11 deletions(-) diff --git a/tests/README.md b/tests/README.md index 496afa0c..2d6f8ff0 100644 --- a/tests/README.md +++ b/tests/README.md @@ -23,6 +23,7 @@ The test script covers the following RBT Transfer scenarios: ## Prerequisites - Python 3.10+ ([Install Ref](https://www.python.org/downloads/)) +- tmux for MacOs and Ubuntu based systems ([Install Ref](https://github.com/tmux/tmux/wiki/Installing#binary-packages)) - `pip` package manger ([Install Ref](https://pip.pypa.io/en/stable/installation/)) - `requests` package. After installing Python and pip, run `pip install requests` to install this package diff --git a/tests/node/commands.py b/tests/node/commands.py index 42c76f24..542a56df 100644 --- a/tests/node/commands.py +++ b/tests/node/commands.py @@ -1,6 +1,19 @@ import subprocess import os import re +import platform + +def get_build_dir(): + os_name = platform.system() + build_folder = "" + if os_name == "Linux": + build_folder = "linux" + elif os_name == "Windows": + build_folder = "windows" + elif os_name == "Darwin": + build_folder = "mac" + + return build_folder def run_command(cmd_string, is_output_from_stderr=False): assert isinstance(cmd_string, str), "command must be of string type" @@ -28,15 +41,15 @@ def run_command(cmd_string, is_output_from_stderr=False): return output, code def cmd_run_rubix_servers(node_name, server_port_idx, grpc_port): - os.chdir("../linux") - cmd_string = f"screen -S {node_name} -d -m ./rubixgoplatform run -p {node_name} -n {server_port_idx} -s -testNet -grpcPort {grpc_port}" + os.chdir("../" + get_build_dir()) + cmd_string = f"tmux new -s {node_name} -d ./rubixgoplatform run -p {node_name} -n {server_port_idx} -s -testNet -grpcPort {grpc_port}" _, code = run_command(cmd_string) if code != 0: raise Exception("Error occurred while run the command: " + cmd_string) os.chdir("../tests") def cmd_create_did(server_port, grpc_port): - os.chdir("../linux") + os.chdir("../" + get_build_dir()) cmd_string = f"./rubixgoplatform createdid -port {server_port} -grpcPort {grpc_port}" output, code = run_command(cmd_string, True) @@ -56,7 +69,7 @@ def cmd_create_did(server_port, grpc_port): return did_id def cmd_register_did(did_id, server_port, grpc_port): - os.chdir("../linux") + os.chdir("../" + get_build_dir()) cmd_string = f"./rubixgoplatform registerdid -did {did_id} -port {server_port} -grpcPort {grpc_port}" output, code = run_command(cmd_string) print(output) @@ -68,7 +81,7 @@ def cmd_register_did(did_id, server_port, grpc_port): return output def cmd_generate_rbt(did_id, numTokens, server_port, grpc_port): - os.chdir("../linux") + os.chdir("../" + get_build_dir()) cmd_string = f"./rubixgoplatform generatetestrbt -did {did_id} -numTokens {numTokens} -port {server_port} -grpcPort {grpc_port}" output, code = run_command(cmd_string, True) @@ -79,7 +92,7 @@ def cmd_generate_rbt(did_id, numTokens, server_port, grpc_port): return output def cmd_add_quorum_dids(server_port, grpc_port): - os.chdir("../linux") + os.chdir("../" + get_build_dir()) cmd_string = f"./rubixgoplatform addquorum -port {server_port} -grpcPort {grpc_port}" output, code = run_command(cmd_string, True) print(output) @@ -90,7 +103,7 @@ def cmd_add_quorum_dids(server_port, grpc_port): return output def cmd_shutdown_node(server_port, grpc_port): - os.chdir("../linux") + os.chdir("../" + get_build_dir()) cmd_string = f"./rubixgoplatform shutdown -port {server_port} -grpcPort {grpc_port}" output, _ = run_command(cmd_string, True) print(output) @@ -99,7 +112,7 @@ def cmd_shutdown_node(server_port, grpc_port): return output def cmd_setup_quorum_dids(did, server_port, grpc_port): - os.chdir("../linux") + os.chdir("../" + get_build_dir()) cmd_string = f"./rubixgoplatform setupquorum -did {did} -port {server_port} -grpcPort {grpc_port}" output, code = run_command(cmd_string, True) print(output) @@ -110,7 +123,7 @@ def cmd_setup_quorum_dids(did, server_port, grpc_port): return output def cmd_get_peer_id(server_port, grpc_port): - os.chdir("../linux") + os.chdir("../" + get_build_dir()) cmd_string = f"./rubixgoplatform get-peer-id -port {server_port} -grpcPort {grpc_port}" output, code = run_command(cmd_string) @@ -120,7 +133,7 @@ def cmd_get_peer_id(server_port, grpc_port): return output def check_account_info(did, server_port, grpc_port): - os.chdir("../linux") + os.chdir("../" + get_build_dir()) cmd_string = f"./rubixgoplatform getaccountinfo -did {did} -port {server_port} -grpcPort {grpc_port}" output, code = run_command(cmd_string) @@ -131,7 +144,7 @@ def check_account_info(did, server_port, grpc_port): # Note: address != did, address = peerId.didId def cmd_rbt_transfer(sender_address, receiver_address, rbt_amount, server_port, grpc_port): - os.chdir("../linux") + os.chdir("../" + get_build_dir()) cmd_string = f"./rubixgoplatform transferrbt -senderAddr {sender_address} -receiverAddr {receiver_address} -rbtAmount {rbt_amount} -port {server_port} -grpcPort {grpc_port}" output, code = run_command(cmd_string, True) print(output) From 3d12ffac2bf7459541fe1a463d5519fcd5d3a004 Mon Sep 17 00:00:00 2001 From: Arnab Ghose Date: Thu, 9 May 2024 10:02:13 +0530 Subject: [PATCH 026/129] added checks and instructions to support execution in windows os --- tests/fixtures/testswarm.key | 4 +- tests/helper/utils.py | 30 +-- tests/node/actions.py | 221 ++++++++++---------- tests/node/commands.py | 339 +++++++++++++++++-------------- tests/node/quorum.py | 132 ++++++------ tests/node/utils.py | 32 +-- tests/node/vars.py | 4 +- tests/run.py | 343 ++++++++++++++++---------------- tests/scenarios/rbt_transfer.py | 168 ++++++++-------- tests/shutdown.py | 32 +-- 10 files changed, 671 insertions(+), 634 deletions(-) diff --git a/tests/fixtures/testswarm.key b/tests/fixtures/testswarm.key index 8985c5d0..6f0cf118 100644 --- a/tests/fixtures/testswarm.key +++ b/tests/fixtures/testswarm.key @@ -1,3 +1,3 @@ -/key/swarm/psk/1.0.0/ -/base16/ +/key/swarm/psk/1.0.0/ +/base16/ 278b9a199c43fa84178920bd9f5cbcd69e933ddf02a8f69e47a3ea5a1705512f \ No newline at end of file diff --git a/tests/helper/utils.py b/tests/helper/utils.py index 8011a780..68d8649f 100644 --- a/tests/helper/utils.py +++ b/tests/helper/utils.py @@ -1,16 +1,16 @@ -def expect_success(func): - def wrapper(*args, **kwargs): - try: - func(*args, **kwargs) - except: - raise Exception("The action was expected to pass, but it failed") - return wrapper - -def expect_failure(func): - def wrapper(*args, **kwargs): - try: - func(*args, **kwargs) - raise Exception("The action was expected to fail, but it passed") - except: - return 0 +def expect_success(func): + def wrapper(*args, **kwargs): + try: + func(*args, **kwargs) + except: + raise Exception("The action was expected to pass, but it failed") + return wrapper + +def expect_failure(func): + def wrapper(*args, **kwargs): + try: + func(*args, **kwargs) + raise Exception("The action was expected to fail, but it passed") + except: + return 0 return wrapper \ No newline at end of file diff --git a/tests/node/actions.py b/tests/node/actions.py index 7251f265..9cc014e4 100644 --- a/tests/node/actions.py +++ b/tests/node/actions.py @@ -1,111 +1,112 @@ -from .commands import cmd_run_rubix_servers, cmd_get_peer_id, cmd_create_did, cmd_register_did, \ - cmd_generate_rbt, cmd_add_quorum_dids, cmd_setup_quorum_dids, cmd_rbt_transfer -from .utils import get_node_name_from_idx, save_to_json - -def add_quorums(node_config: dict): - for config in node_config.values(): - cmd_add_quorum_dids( - config["server"], - config["grpcPort"] - ) - -def setup_quorums(node_config: dict): - for config in node_config.values(): - cmd_setup_quorum_dids( - config["did"], - config["server"], - config["grpcPort"] - ) - -def quorum_config(node_config: dict, skip_adding_quorums: bool = False, create_quorum_list: bool = False): - # Prepare quorumlist.json - quorum_list = [] - if create_quorum_list: - for config in node_config.values(): - quorum_info = { - "type": 2, - "address": config["peerId"] + "." + config["did"] - } - - quorum_list_file_path = "../linux/quorumlist.json" # TODO: make it Dynamic - quorum_list.append(quorum_info) - - save_to_json(quorum_list_file_path, quorum_list) - - # # add quorums - if not skip_adding_quorums: - add_quorums(node_config) - - setup_quorums(node_config) - - -def get_base_ports(): - base_ens_server = 20000 - base_grpc_port = 10500 - - return base_ens_server, base_grpc_port - -def setup_rubix_nodes(node_count: int = 0, node_prefix_str: str = "node"): - base_ens_server, base_grpc_port = get_base_ports() - - node_config = {} - - # Start rubix servers - loop_start_idx, loop_end_idx = 0, node_count - - for i in range(loop_start_idx, loop_end_idx): - k = i if node_prefix_str == "node" else (10+i) - - ens_server = base_ens_server + k - print(f"Running server at port: {ens_server}") - grpc_port = base_grpc_port + k - - node_name = get_node_name_from_idx(k, node_prefix_str) - - cmd_run_rubix_servers(node_name, k, grpc_port) - - node_config[node_name] = { - "did": "", - "server": ens_server, - "grpcPort": grpc_port, - "peerId": "" - } - - return node_config - - -def fetch_peer_ids(node_config: dict): - print("Fetching Node IDs........") - for config in node_config.values(): - peer_id = cmd_get_peer_id(config["server"], config["grpcPort"]) - config["peerId"] = peer_id - print("Fetched all Node IDs") - - -def create_and_register_did(node_config: dict, register_did: bool = True): - for config in node_config.values(): - did_id = cmd_create_did(config["server"], config["grpcPort"]) - print("Created DID : ", did_id) - - if register_did: - print(f"Registering DID: {did_id}") - cmd_register_did(did_id, config["server"], config["grpcPort"]) - print("DID is registered successfully\n") - - config["did"] = did_id - -def fund_dids_with_rbt(node_config: dict, rbt_amount: int = 30): - for config in node_config.values(): - cmd_generate_rbt(config["did"], rbt_amount, config["server"], config["grpcPort"]) - print("DID ", config["did"], f" is funded with {rbt_amount} RBT") - -def fund_did_with_rbt(config: dict, rbt_amount: int = 30): - output = cmd_generate_rbt(config["did"], rbt_amount, config["server"], config["grpcPort"]) - print(output) - return output - -def rbt_transfer(config_sender: dict, config_receiver: dict, transfer_rbt_amount: int): - sender_address = config_sender["peerId"] + "." + config_sender["did"] - receiver_address = config_receiver["peerId"] + "." + config_receiver["did"] - +from .commands import cmd_run_rubix_servers, cmd_get_peer_id, cmd_create_did, cmd_register_did, \ + cmd_generate_rbt, cmd_add_quorum_dids, cmd_setup_quorum_dids, cmd_rbt_transfer, get_build_dir +from .utils import get_node_name_from_idx, save_to_json + +def add_quorums(node_config: dict): + for config in node_config.values(): + cmd_add_quorum_dids( + config["server"], + config["grpcPort"] + ) + +def setup_quorums(node_config: dict): + for config in node_config.values(): + cmd_setup_quorum_dids( + config["did"], + config["server"], + config["grpcPort"] + ) + +def quorum_config(node_config: dict, skip_adding_quorums: bool = False, create_quorum_list: bool = False): + # Prepare quorumlist.json + quorum_list = [] + if create_quorum_list: + for config in node_config.values(): + quorum_info = { + "type": 2, + "address": config["peerId"] + "." + config["did"] + } + + build_dir = get_build_dir() + quorum_list_file_path = f"../{build_dir}/quorumlist.json" + quorum_list.append(quorum_info) + + save_to_json(quorum_list_file_path, quorum_list) + + # # add quorums + if not skip_adding_quorums: + add_quorums(node_config) + + setup_quorums(node_config) + + +def get_base_ports(): + base_ens_server = 20000 + base_grpc_port = 10500 + + return base_ens_server, base_grpc_port + +def setup_rubix_nodes(node_count: int = 0, node_prefix_str: str = "node"): + base_ens_server, base_grpc_port = get_base_ports() + + node_config = {} + + # Start rubix servers + loop_start_idx, loop_end_idx = 0, node_count + + for i in range(loop_start_idx, loop_end_idx): + k = i if node_prefix_str == "node" else (10+i) + + ens_server = base_ens_server + k + print(f"Running server at port: {ens_server}") + grpc_port = base_grpc_port + k + + node_name = get_node_name_from_idx(k, node_prefix_str) + + cmd_run_rubix_servers(node_name, k, grpc_port) + + node_config[node_name] = { + "did": "", + "server": ens_server, + "grpcPort": grpc_port, + "peerId": "" + } + + return node_config + + +def fetch_peer_ids(node_config: dict): + print("Fetching Node IDs........") + for config in node_config.values(): + peer_id = cmd_get_peer_id(config["server"], config["grpcPort"]) + config["peerId"] = peer_id + print("Fetched all Node IDs") + + +def create_and_register_did(node_config: dict, register_did: bool = True): + for config in node_config.values(): + did_id = cmd_create_did(config["server"], config["grpcPort"]) + print("Created DID : ", did_id) + + if register_did: + print(f"Registering DID: {did_id}") + cmd_register_did(did_id, config["server"], config["grpcPort"]) + print("DID is registered successfully\n") + + config["did"] = did_id + +def fund_dids_with_rbt(node_config: dict, rbt_amount: int = 30): + for config in node_config.values(): + cmd_generate_rbt(config["did"], rbt_amount, config["server"], config["grpcPort"]) + print("DID ", config["did"], f" is funded with {rbt_amount} RBT") + +def fund_did_with_rbt(config: dict, rbt_amount: int = 30): + output = cmd_generate_rbt(config["did"], rbt_amount, config["server"], config["grpcPort"]) + print(output) + return output + +def rbt_transfer(config_sender: dict, config_receiver: dict, transfer_rbt_amount: int): + sender_address = config_sender["peerId"] + "." + config_sender["did"] + receiver_address = config_receiver["peerId"] + "." + config_receiver["did"] + cmd_rbt_transfer(sender_address, receiver_address, transfer_rbt_amount, config_sender["server"], config_sender["grpcPort"]) \ No newline at end of file diff --git a/tests/node/commands.py b/tests/node/commands.py index 542a56df..8ca91ce3 100644 --- a/tests/node/commands.py +++ b/tests/node/commands.py @@ -1,155 +1,186 @@ -import subprocess -import os -import re -import platform - -def get_build_dir(): - os_name = platform.system() - build_folder = "" - if os_name == "Linux": - build_folder = "linux" - elif os_name == "Windows": - build_folder = "windows" - elif os_name == "Darwin": - build_folder = "mac" - - return build_folder - -def run_command(cmd_string, is_output_from_stderr=False): - assert isinstance(cmd_string, str), "command must be of string type" - cmd_result = subprocess.run(cmd_string, stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=True) - code = cmd_result.returncode - - if int(code) != 0: - err_output = cmd_result.stderr.decode('utf-8')[:-1] - print(err_output) - return err_output, int(code) - - output = "" - if not is_output_from_stderr: - output = cmd_result.stdout.decode('utf-8')[:-1] - print(output) - if output.find('[ERROR]') > 0 or output.find('parse error') > 0: - return output, 1 - else: - return output, code - else: - output = cmd_result.stderr.decode('utf-8')[:-1] - if output.find('[ERROR]') > 0 or output.find('parse error') > 0: - return output, 1 - else: - return output, code - -def cmd_run_rubix_servers(node_name, server_port_idx, grpc_port): - os.chdir("../" + get_build_dir()) - cmd_string = f"tmux new -s {node_name} -d ./rubixgoplatform run -p {node_name} -n {server_port_idx} -s -testNet -grpcPort {grpc_port}" - _, code = run_command(cmd_string) - if code != 0: - raise Exception("Error occurred while run the command: " + cmd_string) - os.chdir("../tests") - -def cmd_create_did(server_port, grpc_port): - os.chdir("../" + get_build_dir()) - cmd_string = f"./rubixgoplatform createdid -port {server_port} -grpcPort {grpc_port}" - output, code = run_command(cmd_string, True) - - if code != 0: - raise Exception("Error occurred while run the command: " + cmd_string) - - did_id = "" - if "successfully" in output: - pattern = r'bafybmi\w+' - matches = re.findall(pattern, output) - if matches: - did_id = matches[0] - else: - raise Exception("unable to extract DID ID") - - os.chdir("../tests") - return did_id - -def cmd_register_did(did_id, server_port, grpc_port): - os.chdir("../" + get_build_dir()) - cmd_string = f"./rubixgoplatform registerdid -did {did_id} -port {server_port} -grpcPort {grpc_port}" - output, code = run_command(cmd_string) - print(output) - - if code != 0: - raise Exception("Error occurred while run the command: " + cmd_string) - - os.chdir("../tests") - return output - -def cmd_generate_rbt(did_id, numTokens, server_port, grpc_port): - os.chdir("../" + get_build_dir()) - cmd_string = f"./rubixgoplatform generatetestrbt -did {did_id} -numTokens {numTokens} -port {server_port} -grpcPort {grpc_port}" - output, code = run_command(cmd_string, True) - - if code != 0: - raise Exception("Error occurred while run the command: " + cmd_string) - - os.chdir("../tests") - return output - -def cmd_add_quorum_dids(server_port, grpc_port): - os.chdir("../" + get_build_dir()) - cmd_string = f"./rubixgoplatform addquorum -port {server_port} -grpcPort {grpc_port}" - output, code = run_command(cmd_string, True) - print(output) - if code != 0: - raise Exception("Error occurred while run the command: " + cmd_string) - - os.chdir("../tests") - return output - -def cmd_shutdown_node(server_port, grpc_port): - os.chdir("../" + get_build_dir()) - cmd_string = f"./rubixgoplatform shutdown -port {server_port} -grpcPort {grpc_port}" - output, _ = run_command(cmd_string, True) - print(output) - - os.chdir("../tests") - return output - -def cmd_setup_quorum_dids(did, server_port, grpc_port): - os.chdir("../" + get_build_dir()) - cmd_string = f"./rubixgoplatform setupquorum -did {did} -port {server_port} -grpcPort {grpc_port}" - output, code = run_command(cmd_string, True) - print(output) - if code != 0: - raise Exception("Error occurred while run the command: " + cmd_string) - - os.chdir("../tests") - return output - -def cmd_get_peer_id(server_port, grpc_port): - os.chdir("../" + get_build_dir()) - cmd_string = f"./rubixgoplatform get-peer-id -port {server_port} -grpcPort {grpc_port}" - output, code = run_command(cmd_string) - - if code != 0: - raise Exception("Error occurred while run the command: " + cmd_string) - os.chdir("../tests") - return output - -def check_account_info(did, server_port, grpc_port): - os.chdir("../" + get_build_dir()) - cmd_string = f"./rubixgoplatform getaccountinfo -did {did} -port {server_port} -grpcPort {grpc_port}" - output, code = run_command(cmd_string) - - if code != 0: - raise Exception("Error occurred while run the command: " + cmd_string) - os.chdir("../tests") - return output - -# Note: address != did, address = peerId.didId -def cmd_rbt_transfer(sender_address, receiver_address, rbt_amount, server_port, grpc_port): - os.chdir("../" + get_build_dir()) - cmd_string = f"./rubixgoplatform transferrbt -senderAddr {sender_address} -receiverAddr {receiver_address} -rbtAmount {rbt_amount} -port {server_port} -grpcPort {grpc_port}" - output, code = run_command(cmd_string, True) - print(output) - if code != 0: - raise Exception("Error occurred while run the command: " + cmd_string) - - os.chdir("../tests") +import subprocess +import os +import re +import platform + +def is_windows_os(): + os_name = platform.system() + return os_name == "Windows" + +def get_build_dir(): + os_name = platform.system() + build_folder = "" + if os_name == "Linux": + build_folder = "linux" + elif os_name == "Windows": + build_folder = "windows" + elif os_name == "Darwin": + build_folder = "mac" + + return build_folder + +def run_command(cmd_string, is_output_from_stderr=False): + assert isinstance(cmd_string, str), "command must be of string type" + cmd_result = subprocess.run(cmd_string, stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=True) + code = cmd_result.returncode + + if int(code) != 0: + err_output = cmd_result.stderr.decode('utf-8')[:-1] + print(err_output) + return err_output, int(code) + + output = "" + if not is_output_from_stderr: + output = cmd_result.stdout.decode('utf-8')[:-1] + print(output) + if output.find('[ERROR]') > 0 or output.find('parse error') > 0: + return output, 1 + else: + return output, code + else: + output = cmd_result.stderr.decode('utf-8')[:-1] + if output.find('[ERROR]') > 0 or output.find('parse error') > 0: + print(output) + return output, 1 + else: + return output, code + +def cmd_run_rubix_servers(node_name, server_port_idx, grpc_port): + os.chdir("../" + get_build_dir()) + + cmd_string = "" + if is_windows_os(): + #cmd = f".\\rubixgoplatform run -p {node_name} -n {server_port_idx} -s -testNet -grpcPort {grpc_port}" + cmd_string = f"powershell -Command Start-Process -FilePath '.\\rubixgoplatform.exe' -ArgumentList 'run -p {node_name} -n {server_port_idx} -s -testNet -grpcPort {grpc_port}' -WindowStyle Hidden" + else: + cmd_string = f"tmux new -s {node_name} -d ./rubixgoplatform run -p {node_name} -n {server_port_idx} -s -testNet -grpcPort {grpc_port}" + + _, code = run_command(cmd_string) + if code != 0: + raise Exception("Error occurred while run the command: " + cmd_string) + os.chdir("../tests") + +def cmd_create_did(server_port, grpc_port): + os.chdir("../" + get_build_dir()) + + cmd_string = f"./rubixgoplatform createdid -port {server_port} -grpcPort {grpc_port}" + if is_windows_os(): + cmd_string = f".\\rubixgoplatform createdid -port {server_port} -grpcPort {grpc_port}" + output, code = run_command(cmd_string, True) + + if code != 0: + raise Exception("Error occurred while run the command: " + cmd_string) + + did_id = "" + if "successfully" in output: + pattern = r'bafybmi\w+' + matches = re.findall(pattern, output) + if matches: + did_id = matches[0] + else: + raise Exception("unable to extract DID ID") + + os.chdir("../tests") + return did_id + +def cmd_register_did(did_id, server_port, grpc_port): + os.chdir("../" + get_build_dir()) + cmd_string = f"./rubixgoplatform registerdid -did {did_id} -port {server_port} -grpcPort {grpc_port}" + if is_windows_os(): + cmd_string = f".\\rubixgoplatform registerdid -did {did_id} -port {server_port} -grpcPort {grpc_port}" + output, code = run_command(cmd_string) + print(output) + + if code != 0: + raise Exception("Error occurred while run the command: " + cmd_string) + + os.chdir("../tests") + return output + +def cmd_generate_rbt(did_id, numTokens, server_port, grpc_port): + os.chdir("../" + get_build_dir()) + cmd_string = f"./rubixgoplatform generatetestrbt -did {did_id} -numTokens {numTokens} -port {server_port} -grpcPort {grpc_port}" + if is_windows_os(): + cmd_string = f".\\rubixgoplatform generatetestrbt -did {did_id} -numTokens {numTokens} -port {server_port} -grpcPort {grpc_port}" + output, code = run_command(cmd_string, True) + + if code != 0: + raise Exception("Error occurred while run the command: " + cmd_string) + + os.chdir("../tests") + return output + +def cmd_add_quorum_dids(server_port, grpc_port): + os.chdir("../" + get_build_dir()) + cmd_string = f"./rubixgoplatform addquorum -port {server_port} -grpcPort {grpc_port}" + if is_windows_os(): + cmd_string = f".\\rubixgoplatform addquorum -port {server_port} -grpcPort {grpc_port}" + output, code = run_command(cmd_string, True) + print(output) + if code != 0: + raise Exception("Error occurred while run the command: " + cmd_string) + + os.chdir("../tests") + return output + +def cmd_shutdown_node(server_port, grpc_port): + os.chdir("../" + get_build_dir()) + cmd_string = f"./rubixgoplatform shutdown -port {server_port} -grpcPort {grpc_port}" + if is_windows_os(): + cmd_string = f".\\rubixgoplatform shutdown -port {server_port} -grpcPort {grpc_port}" + output, _ = run_command(cmd_string, True) + print(output) + + os.chdir("../tests") + return output + +def cmd_setup_quorum_dids(did, server_port, grpc_port): + os.chdir("../" + get_build_dir()) + cmd_string = f"./rubixgoplatform setupquorum -did {did} -port {server_port} -grpcPort {grpc_port}" + if is_windows_os(): + cmd_string = f".\\rubixgoplatform setupquorum -did {did} -port {server_port} -grpcPort {grpc_port}" + output, code = run_command(cmd_string, True) + print(output) + if code != 0: + raise Exception("Error occurred while run the command: " + cmd_string) + + os.chdir("../tests") + return output + +def cmd_get_peer_id(server_port, grpc_port): + os.chdir("../" + get_build_dir()) + cmd_string = f"./rubixgoplatform get-peer-id -port {server_port} -grpcPort {grpc_port}" + if is_windows_os(): + cmd_string = f".\\rubixgoplatform get-peer-id -port {server_port} -grpcPort {grpc_port}" + output, code = run_command(cmd_string) + + if code != 0: + raise Exception("Error occurred while run the command: " + cmd_string) + os.chdir("../tests") + return output + +def check_account_info(did, server_port, grpc_port): + os.chdir("../" + get_build_dir()) + cmd_string = f"./rubixgoplatform getaccountinfo -did {did} -port {server_port} -grpcPort {grpc_port}" + if is_windows_os(): + cmd_string = f".\\rubixgoplatform getaccountinfo -did {did} -port {server_port} -grpcPort {grpc_port}" + output, code = run_command(cmd_string) + + if code != 0: + raise Exception("Error occurred while run the command: " + cmd_string) + os.chdir("../tests") + return output + +# Note: address != did, address = peerId.didId +def cmd_rbt_transfer(sender_address, receiver_address, rbt_amount, server_port, grpc_port): + os.chdir("../" + get_build_dir()) + cmd_string = f"./rubixgoplatform transferrbt -senderAddr {sender_address} -receiverAddr {receiver_address} -rbtAmount {rbt_amount} -port {server_port} -grpcPort {grpc_port}" + if is_windows_os(): + cmd_string = f".\\rubixgoplatform transferrbt -senderAddr {sender_address} -receiverAddr {receiver_address} -rbtAmount {rbt_amount} -port {server_port} -grpcPort {grpc_port}" + output, code = run_command(cmd_string, True) + print(output) + if code != 0: + raise Exception("Error occurred while run the command: " + cmd_string) + + os.chdir("../tests") return output \ No newline at end of file diff --git a/tests/node/quorum.py b/tests/node/quorum.py index b8ca59d7..ba5de3d3 100644 --- a/tests/node/quorum.py +++ b/tests/node/quorum.py @@ -1,67 +1,67 @@ -import pprint -import time - -from .actions import setup_rubix_nodes, fetch_peer_ids, create_and_register_did, \ - fund_dids_with_rbt, quorum_config -from .utils import save_to_json - -def run_quorum_nodes(node_config_path, only_run_nodes, skip_adding_quorums): - node_config_path = "./quorum_config.json" - - print("Running Rubix nodes......") - node_config = setup_rubix_nodes(5) - print("Rubix nodes are now running") - - if not only_run_nodes: - print("Waiting 20 seconds before fetching all node peer IDs............") - time.sleep(20) - - fetch_peer_ids(node_config) - - print("Creation and registeration of quorum DIDs have started") - create_and_register_did(node_config) - print("All quorum DIDs have been registered") - - print("Initiating funding of these quorum DIDs") - fund_dids_with_rbt(node_config) - print("All Quorum DIDs have been funded") - - save_to_json(node_config_path, node_config) - - print("Setting up quorums and saving information about them to quorumlist.json") - quorum_config(node_config, skip_adding_quorums=skip_adding_quorums, create_quorum_list=True) - - pprint.pp(node_config) - print("Quorums have been configured. You can proceed with running Test scenarios") - else: - quorum_config(node_config, skip_adding_quorums=True, create_quorum_list=False) - - return node_config - -def run_non_quorum_nodes(node_config_path, only_run_nodes, skip_adding_quorums): - node_config_path = "./non_quorum_config.json" - - print("Running non-quorum nodes...") - node_config = setup_rubix_nodes(2, "nodeNq") - print("Non-quorum nodes are running successfully") - - if not only_run_nodes: - print("Waiting 20 seconds before fetching all node peer IDs............") - time.sleep(20) - fetch_peer_ids(node_config) - - print("Creation of Non Quorum DIDs have started") - create_and_register_did(node_config, False) - print("Non Quorum DIDs have been created") - - save_to_json(node_config_path, node_config) - - print("Adding and setting up quorum config") - quorum_config(node_config, skip_adding_quorums=skip_adding_quorums, create_quorum_list=False) - - pprint.pp(node_config) - print("Non Quorum nodes have been configured") - else: - quorum_config(node_config, skip_adding_quorums=True, create_quorum_list=False) - +import pprint +import time + +from .actions import setup_rubix_nodes, fetch_peer_ids, create_and_register_did, \ + fund_dids_with_rbt, quorum_config +from .utils import save_to_json + +def run_quorum_nodes(node_config_path, only_run_nodes, skip_adding_quorums): + node_config_path = "./quorum_config.json" + + print("Running Rubix nodes......") + node_config = setup_rubix_nodes(5) + print("Rubix nodes are now running") + + if not only_run_nodes: + print("Waiting 60 seconds before fetching all node peer IDs............") + time.sleep(60) + + fetch_peer_ids(node_config) + + print("Creation and registeration of quorum DIDs have started") + create_and_register_did(node_config) + print("All quorum DIDs have been registered") + + print("Initiating funding of these quorum DIDs") + fund_dids_with_rbt(node_config) + print("All Quorum DIDs have been funded") + + save_to_json(node_config_path, node_config) + + print("Setting up quorums and saving information about them to quorumlist.json") + quorum_config(node_config, skip_adding_quorums=skip_adding_quorums, create_quorum_list=True) + + pprint.pp(node_config) + print("Quorums have been configured") + else: + quorum_config(node_config, skip_adding_quorums=True, create_quorum_list=False) + + return node_config + +def run_non_quorum_nodes(node_config_path, only_run_nodes, skip_adding_quorums): + node_config_path = "./non_quorum_config.json" + + print("Running non-quorum nodes...") + node_config = setup_rubix_nodes(2, "nodeNq") + print("Non-quorum nodes are running successfully") + + if not only_run_nodes: + print("Waiting 30 seconds before fetching all node peer IDs............") + time.sleep(30) + fetch_peer_ids(node_config) + + print("Creation of Non Quorum DIDs have started") + create_and_register_did(node_config, False) + print("Non Quorum DIDs have been created") + + save_to_json(node_config_path, node_config) + + print("Adding and setting up quorum config") + quorum_config(node_config, skip_adding_quorums=skip_adding_quorums, create_quorum_list=False) + + pprint.pp(node_config) + print("Non Quorum nodes have been configured") + else: + quorum_config(node_config, skip_adding_quorums=True, create_quorum_list=False) + return node_config \ No newline at end of file diff --git a/tests/node/utils.py b/tests/node/utils.py index 61bcdbe7..a30cfa47 100644 --- a/tests/node/utils.py +++ b/tests/node/utils.py @@ -1,16 +1,16 @@ -import json -import sys -import os -sys.path.insert(1, os.getcwd()) -from .vars import QUORUM_NODES - -def get_node_name_from_idx(idx, prefix_string: str = "node"): - return prefix_string + str(idx) - -def save_to_json(filepath, obj): - # Check if file exists. If yes, then remove it - if os.path.exists(filepath): - os.remove(filepath) - - with open(filepath, 'w') as f: - json.dump(obj, f, indent=4) +import json +import sys +import os +sys.path.insert(1, os.getcwd()) +from .vars import QUORUM_NODES + +def get_node_name_from_idx(idx, prefix_string: str = "node"): + return prefix_string + str(idx) + +def save_to_json(filepath, obj): + # Check if file exists. If yes, then remove it + if os.path.exists(filepath): + os.remove(filepath) + + with open(filepath, 'w') as f: + json.dump(obj, f, indent=4) diff --git a/tests/node/vars.py b/tests/node/vars.py index 7b683fcb..1cdf27f6 100644 --- a/tests/node/vars.py +++ b/tests/node/vars.py @@ -1,2 +1,2 @@ -QUORUM_NODES = 5 - +QUORUM_NODES = 5 + diff --git a/tests/run.py b/tests/run.py index 7e8c091b..6dbaf35a 100644 --- a/tests/run.py +++ b/tests/run.py @@ -1,169 +1,174 @@ -import platform -import os -import shutil -import requests -import argparse -from node.commands import run_command -from node.quorum import run_quorum_nodes, run_non_quorum_nodes -from scenarios.rbt_transfer import * - -IPFS_KUBO_VERSION = "v0.21.0" -QUORUM_CONFIG_FILE = "./quorum_config.json" -NON_QUORUM_CONFIG_FILE = "./non_quorum_config.json" - -def get_os_info(): - os_name = platform.system() - build_folder = "" - - if os_name == "Linux": - build_folder = "linux" - elif os_name == "Windows": - build_folder = "windows" - elif os_name == "Darwin": - build_folder = "mac" - else: - print("Unsupported operating system to build Rubix") - return None, None - - return os_name, build_folder - -def download_ipfs_binary(os_name, version, build_dir): - download_url = "" - - if os_name == "Linux": - download_url = f"https://dist.ipfs.tech/kubo/{version}/kubo_{version}_linux-amd64.tar.gz" - elif os_name == "Windows": - download_url = f"https://dist.ipfs.tech/kubo/{version}/kubo_{version}_windows-amd64.zip" - elif os_name == "Darwin": # MacOS - download_url = f"https://dist.ipfs.tech/kubo/{version}/kubo_{version}_darwin-amd64.tar.gz" - else: - raise ValueError("Unsupported operating system") - - # Download the IPFS binary archive - download_path = f"kubo_{version}_{os_name.lower()}-amd64.tar.gz" if os_name != "Windows" else f"kubo_{version}_{os_name.lower()}-amd64.zip" - print("Downloading IPFS binary...") - response = requests.get(download_url) - with open(download_path, "wb") as f: - f.write(response.content) - print("Download completed.") - - # Extract the archive - print("Extracting IPFS binary...") - if os_name == "Windows": - # For Windows, we need to use the 'zipfile' module to extract - import zipfile - with zipfile.ZipFile(download_path, "r") as zip_ref: - zip_ref.extractall("kubo") - else: - # For Linux and MacOS, we use tar - import tarfile - with tarfile.open(download_path, "r:gz" if os_name != "Darwin" else "r") as tar_ref: - tar_ref.extractall("kubo") - print("Extraction completed.") - - # Check the contents of the kubo directory - print("Contents of kubo directory:") - for item in os.listdir("kubo"): - print(item) - - # Move IPFS binary to the appropriate folder - print("Moving IPFS binary...") - src_file = os.path.join("kubo", "kubo", "ipfs") - dest_dir = os.path.join(build_dir, "ipfs") - if os.path.exists(src_file): - shutil.move(src_file, dest_dir) - print("IPFS binary moved to", dest_dir) - - # Check if the file is present at the destination - dest_file = os.path.join(dest_dir) - if not os.path.exists(dest_file): - raise FileNotFoundError("IPFS binary not found at the destination after move operation.") - else: - raise FileNotFoundError("Installed IPFS binary file does not exist.") - - # Clean up - os.remove(download_path) - shutil.rmtree("kubo") - print("\nIPFS has been installed succesfully.") - -def copy_fixtures_to_build_dir(build_directory): - fixtures_directory = os.path.join("tests", "fixtures") - - # Copy didimage.png.file - image_file_src = os.path.join(fixtures_directory, "didimage.png.file") - image_file_dest = os.path.join(build_directory, "image.png") - shutil.copyfile(image_file_src, image_file_dest) - - if not os.path.exists(image_file_dest): - raise FileNotFoundError(f"Copy operation for didimage.png.file failed. Destination file not found: {image_file_dest}") - - # Copy testswarm.key - swarmkey_src = os.path.join(fixtures_directory, "testswarm.key") - swarmkey_dest = os.path.join(build_directory, "testswarm.key") - shutil.copyfile(swarmkey_src, swarmkey_dest) - - if not os.path.exists(swarmkey_dest): - raise FileNotFoundError(f"Copy operation for testswarm.key failed. Destination file not found: {swarmkey_dest}") - - print("\nimage.png and swarm key have been added to build directory successfully") - -def cli(): - parser = argparse.ArgumentParser(description="CLI to run tests for Rubix") - parser.add_argument("--skip_prerequisite", action=argparse.BooleanOptionalAction, help="skip prerequisite steps such as installing IPFS and building Rubix") - parser.add_argument("--run_nodes_only", action=argparse.BooleanOptionalAction, help="only run the rubix nodes and skip the setup") - parser.add_argument("--skip_adding_quorums", action=argparse.BooleanOptionalAction, help="skips adding quorums") - parser.add_argument("--run_tests_only", action=argparse.BooleanOptionalAction, help="only proceed with running tests") - return parser.parse_args() - - -if __name__=='__main__': - os.chdir("../") - - args = cli() - skip_prerequisite = args.skip_prerequisite - run_nodes_only = args.run_nodes_only - skip_adding_quorums = args.skip_adding_quorums - run_tests_only = args.run_tests_only - - non_quorum_node_config = {} - - if not run_tests_only: - os_name, build_folder = get_os_info() - if os_name is None: - exit(1) - - if not skip_prerequisite: - print(f"Building Rubix binary for {os_name}\n") - build_command = "" - if os_name == "Linux": - build_command = "make compile-linux" - elif os_name == "Windows": - build_command = "make compile-windows" - elif os_name == "Darwin": - build_command = "make compile-mac" - - output, code = run_command(build_command) - if code != 0: - print("build failed with error:", output) - exit(1) - else: - print("\nBuild successful\n") - - - download_ipfs_binary(os_name, IPFS_KUBO_VERSION, build_folder) - copy_fixtures_to_build_dir(build_folder) - os.chdir("./tests") - - run_quorum_nodes(QUORUM_CONFIG_FILE, run_nodes_only, skip_adding_quorums=skip_adding_quorums) - - non_quorum_node_config = run_non_quorum_nodes(NON_QUORUM_CONFIG_FILE, run_nodes_only, skip_adding_quorums=skip_adding_quorums) - - # Run RBT Transfer related tests - rbt_transfer_test_list = [ - shuttle_transfer, - insufficient_balance_transfer, - max_decimal_place_transfer - ] - for testFn in rbt_transfer_test_list: - testFn(non_quorum_node_config) - +import platform +import os +import shutil +import requests +import argparse +from node.commands import run_command +from node.quorum import run_quorum_nodes, run_non_quorum_nodes +from scenarios.rbt_transfer import * + +IPFS_KUBO_VERSION = "v0.21.0" +QUORUM_CONFIG_FILE = "./quorum_config.json" +NON_QUORUM_CONFIG_FILE = "./non_quorum_config.json" + +def get_os_info(): + os_name = platform.system() + build_folder = "" + + if os_name == "Linux": + build_folder = "linux" + elif os_name == "Windows": + build_folder = "windows" + elif os_name == "Darwin": + build_folder = "mac" + else: + print("Unsupported operating system to build Rubix") + return None, None + + return os_name, build_folder + +def download_ipfs_binary(os_name, version, build_dir): + download_url = "" + + if os_name == "Linux": + download_url = f"https://dist.ipfs.tech/kubo/{version}/kubo_{version}_linux-amd64.tar.gz" + elif os_name == "Windows": + download_url = f"https://dist.ipfs.tech/kubo/{version}/kubo_{version}_windows-amd64.zip" + elif os_name == "Darwin": # MacOS + download_url = f"https://dist.ipfs.tech/kubo/{version}/kubo_{version}_darwin-amd64.tar.gz" + else: + raise ValueError("Unsupported operating system") + + # Download the IPFS binary archive + download_path = f"kubo_{version}_{os_name.lower()}-amd64.tar.gz" if os_name != "Windows" else f"kubo_{version}_{os_name.lower()}-amd64.zip" + print("Downloading IPFS binary...") + response = requests.get(download_url) + with open(download_path, "wb") as f: + f.write(response.content) + print("Download completed.") + + # Extract the archive + print("Extracting IPFS binary...") + if os_name == "Windows": + # For Windows, we need to use the 'zipfile' module to extract + import zipfile + with zipfile.ZipFile(download_path, "r") as zip_ref: + zip_ref.extractall("kubo") + else: + # For Linux and MacOS, we use tar + import tarfile + with tarfile.open(download_path, "r:gz" if os_name != "Darwin" else "r") as tar_ref: + tar_ref.extractall("kubo") + print("Extraction completed.") + + # Check the contents of the kubo directory + print("Contents of kubo directory:") + for item in os.listdir("kubo"): + print(item) + + # Move IPFS binary to the appropriate folder + print("Moving IPFS binary...") + + ipfs_bin_name = "ipfs" + if os_name == "Windows": + ipfs_bin_name = "ipfs.exe" + + src_file = os.path.join("kubo", "kubo", ipfs_bin_name) + dest_dir = os.path.join(build_dir, ipfs_bin_name) + if os.path.exists(src_file): + shutil.move(src_file, dest_dir) + print("IPFS binary moved to", dest_dir) + + # Check if the file is present at the destination + dest_file = os.path.join(dest_dir) + if not os.path.exists(dest_file): + raise FileNotFoundError("IPFS binary not found at the destination after move operation.") + else: + raise FileNotFoundError("Installed IPFS binary file does not exist.") + + # Clean up + os.remove(download_path) + shutil.rmtree("kubo") + print("\nIPFS has been installed succesfully.") + +def copy_fixtures_to_build_dir(build_directory): + fixtures_directory = os.path.join("tests", "fixtures") + + # Copy didimage.png.file + image_file_src = os.path.join(fixtures_directory, "didimage.png.file") + image_file_dest = os.path.join(build_directory, "image.png") + shutil.copyfile(image_file_src, image_file_dest) + + if not os.path.exists(image_file_dest): + raise FileNotFoundError(f"Copy operation for didimage.png.file failed. Destination file not found: {image_file_dest}") + + # Copy testswarm.key + swarmkey_src = os.path.join(fixtures_directory, "testswarm.key") + swarmkey_dest = os.path.join(build_directory, "testswarm.key") + shutil.copyfile(swarmkey_src, swarmkey_dest) + + if not os.path.exists(swarmkey_dest): + raise FileNotFoundError(f"Copy operation for testswarm.key failed. Destination file not found: {swarmkey_dest}") + + print("\nimage.png and swarm key have been added to build directory successfully") + +def cli(): + parser = argparse.ArgumentParser(description="CLI to run tests for Rubix") + parser.add_argument("--skip_prerequisite", action=argparse.BooleanOptionalAction, help="skip prerequisite steps such as installing IPFS and building Rubix") + parser.add_argument("--run_nodes_only", action=argparse.BooleanOptionalAction, help="only run the rubix nodes and skip the setup") + parser.add_argument("--skip_adding_quorums", action=argparse.BooleanOptionalAction, help="skips adding quorums") + parser.add_argument("--run_tests_only", action=argparse.BooleanOptionalAction, help="only proceed with running tests") + return parser.parse_args() + + +if __name__=='__main__': + os.chdir("../") + + args = cli() + skip_prerequisite = args.skip_prerequisite + run_nodes_only = args.run_nodes_only + skip_adding_quorums = args.skip_adding_quorums + run_tests_only = args.run_tests_only + + non_quorum_node_config = {} + + if not run_tests_only: + os_name, build_folder = get_os_info() + if os_name is None: + exit(1) + + if not skip_prerequisite: + print(f"Building Rubix binary for {os_name}\n") + build_command = "" + if os_name == "Linux": + build_command = "make compile-linux" + elif os_name == "Windows": + build_command = "make compile-windows" + elif os_name == "Darwin": + build_command = "make compile-mac" + + output, code = run_command(build_command) + if code != 0: + print("build failed with error:", output) + exit(1) + else: + print("\nBuild successful\n") + + + download_ipfs_binary(os_name, IPFS_KUBO_VERSION, build_folder) + copy_fixtures_to_build_dir(build_folder) + os.chdir("./tests") + + run_quorum_nodes(QUORUM_CONFIG_FILE, run_nodes_only, skip_adding_quorums=skip_adding_quorums) + + non_quorum_node_config = run_non_quorum_nodes(NON_QUORUM_CONFIG_FILE, run_nodes_only, skip_adding_quorums=skip_adding_quorums) + + # Run RBT Transfer related tests + rbt_transfer_test_list = [ + shuttle_transfer, + insufficient_balance_transfer, + max_decimal_place_transfer + ] + for testFn in rbt_transfer_test_list: + testFn(non_quorum_node_config) + diff --git a/tests/scenarios/rbt_transfer.py b/tests/scenarios/rbt_transfer.py index 78454198..f8688744 100644 --- a/tests/scenarios/rbt_transfer.py +++ b/tests/scenarios/rbt_transfer.py @@ -1,84 +1,84 @@ -from node.actions import rbt_transfer, fund_did_with_rbt -from helper.utils import expect_failure, expect_success - -def max_decimal_place_transfer(config): - node_A_info = config["nodeNq10"] - node_B_info = config["nodeNq11"] - - print("------ Test Case (FAIL) : Transferring 0.00000009 RBT from B which is more than allowed decimal places ------") - - print("\nTransferring 0.00000009 RBT from B to A....") - expect_failure(rbt_transfer)(node_B_info, node_A_info, 0.00000009) - - print("\n------ Test Case (FAIL) : Transferring 0.00000009 RBT from B which is more than allowed decimal places completed ------\n") - -def insufficient_balance_transfer(config): - node_A_info = config["nodeNq10"] - node_B_info = config["nodeNq11"] - - print("\n------ Test Case (FAIL) : Transferring 100 RBT from A which has zero balance ------") - - print("\nTransferring 100 RBT from A to B....") - expect_failure(rbt_transfer)(node_A_info, node_B_info, 100) - - print("\n------ Test Case (FAIL) : Transferring 100 RBT from A which has zero balance completed ------\n") - - - print("\n------ Test Case (FAIL) : Transferring 100 RBT from B which has insufficient balance ------") - - print("\nTransferring 100 RBT from B to A....") - expect_failure(rbt_transfer)(node_B_info, node_A_info, 100) - - print("\n------ Test Case (FAIL) : Transferring 100 RBT from B which has insufficient balance completed ------\n") - -def shuttle_transfer(config): - node_A_info = config["nodeNq10"] - node_B_info = config["nodeNq11"] - - print("------ Test Case (PASS): Shuttle transfer started ------\n") - - print("\n1. Generating 2 whole RBT for A") - expect_success(fund_did_with_rbt)(node_A_info, 2) - print("Funded node A with 2 RBT") - - print("\n2. Transferring 0.5 RBT from A to B....") - expect_success(rbt_transfer)(node_A_info, node_B_info, 0.5) - print("Transferred 0.5 RBT from A to B") - - print("\n3. Transferring 1.499 RBT from A to B....") - expect_success(rbt_transfer)(node_A_info, node_B_info, 1.499) - print("Transferred 1.499 RBT from A to B") - - print("\n4. Transferring 0.25 RBT from B to A....") - expect_success(rbt_transfer)(node_B_info, node_A_info, 0.25) - print("Transferred 0.25 RBT from B to A") - - print("\n5. Transferring 0.25 RBT from B to A....") - expect_success(rbt_transfer)(node_B_info, node_A_info, 0.25) - print("Transferred 0.25 RBT from B to A") - - print("\n6. Transferring 0.25 RBT from B to A....") - expect_success(rbt_transfer)(node_B_info, node_A_info, 0.25) - print("Transferred 0.25 RBT from B to A") - - print("\n7. Transferring 0.25 RBT from B to A....") - expect_success(rbt_transfer)(node_B_info, node_A_info, 0.25) - print("Transferred 0.25 RBT from B to A") - - print("\n8. Transferring 1 RBT from A to B....") - expect_success(rbt_transfer)(node_A_info, node_B_info, 1) - print("Transferred 1 RBT from A to B") - - print("\n9. Generating 2 whole RBT for A") - expect_success(fund_did_with_rbt)(node_A_info, 2) - print("Funded node A with 2 RBT") - - print("\n10. Transferring 2 RBT from A to B....") - expect_success(rbt_transfer)(node_A_info, node_B_info, 2) - print("Transferred 2 RBT from A to B") - - print("\n11. Transferring 0.001 RBT from A to B....") - expect_success(rbt_transfer)(node_A_info, node_B_info, 0.001) - print("Transferred 0.001 RBT from A to B") - - print("\n------ Test Case (PASS): Shuttle transfer completed ------\n") +from node.actions import rbt_transfer, fund_did_with_rbt +from helper.utils import expect_failure, expect_success + +def max_decimal_place_transfer(config): + node_A_info = config["nodeNq10"] + node_B_info = config["nodeNq11"] + + print("------ Test Case (FAIL) : Transferring 0.00000009 RBT from B which is more than allowed decimal places ------") + + print("\nTransferring 0.00000009 RBT from B to A....") + expect_failure(rbt_transfer)(node_B_info, node_A_info, 0.00000009) + + print("\n------ Test Case (FAIL) : Transferring 0.00000009 RBT from B which is more than allowed decimal places completed ------\n") + +def insufficient_balance_transfer(config): + node_A_info = config["nodeNq10"] + node_B_info = config["nodeNq11"] + + print("\n------ Test Case (FAIL) : Transferring 100 RBT from A which has zero balance ------") + + print("\nTransferring 100 RBT from A to B....") + expect_failure(rbt_transfer)(node_A_info, node_B_info, 100) + + print("\n------ Test Case (FAIL) : Transferring 100 RBT from A which has zero balance completed ------\n") + + + print("\n------ Test Case (FAIL) : Transferring 100 RBT from B which has insufficient balance ------") + + print("\nTransferring 100 RBT from B to A....") + expect_failure(rbt_transfer)(node_B_info, node_A_info, 100) + + print("\n------ Test Case (FAIL) : Transferring 100 RBT from B which has insufficient balance completed ------\n") + +def shuttle_transfer(config): + node_A_info = config["nodeNq10"] + node_B_info = config["nodeNq11"] + + print("------ Test Case (PASS): Shuttle transfer started ------\n") + + print("\n1. Generating 2 whole RBT for A") + expect_success(fund_did_with_rbt)(node_A_info, 2) + print("Funded node A with 2 RBT") + + print("\n2. Transferring 0.5 RBT from A to B....") + expect_success(rbt_transfer)(node_A_info, node_B_info, 0.5) + print("Transferred 0.5 RBT from A to B") + + print("\n3. Transferring 1.499 RBT from A to B....") + expect_success(rbt_transfer)(node_A_info, node_B_info, 1.499) + print("Transferred 1.499 RBT from A to B") + + print("\n4. Transferring 0.25 RBT from B to A....") + expect_success(rbt_transfer)(node_B_info, node_A_info, 0.25) + print("Transferred 0.25 RBT from B to A") + + print("\n5. Transferring 0.25 RBT from B to A....") + expect_success(rbt_transfer)(node_B_info, node_A_info, 0.25) + print("Transferred 0.25 RBT from B to A") + + print("\n6. Transferring 0.25 RBT from B to A....") + expect_success(rbt_transfer)(node_B_info, node_A_info, 0.25) + print("Transferred 0.25 RBT from B to A") + + print("\n7. Transferring 0.25 RBT from B to A....") + expect_success(rbt_transfer)(node_B_info, node_A_info, 0.25) + print("Transferred 0.25 RBT from B to A") + + print("\n8. Transferring 1 RBT from A to B....") + expect_success(rbt_transfer)(node_A_info, node_B_info, 1) + print("Transferred 1 RBT from A to B") + + print("\n9. Generating 2 whole RBT for A") + expect_success(fund_did_with_rbt)(node_A_info, 2) + print("Funded node A with 2 RBT") + + print("\n10. Transferring 2 RBT from A to B....") + expect_success(rbt_transfer)(node_A_info, node_B_info, 2) + print("Transferred 2 RBT from A to B") + + print("\n11. Transferring 0.001 RBT from A to B....") + expect_success(rbt_transfer)(node_A_info, node_B_info, 0.001) + print("Transferred 0.001 RBT from A to B") + + print("\n------ Test Case (PASS): Shuttle transfer completed ------\n") diff --git a/tests/shutdown.py b/tests/shutdown.py index 05c6a090..5e9d2399 100644 --- a/tests/shutdown.py +++ b/tests/shutdown.py @@ -1,16 +1,16 @@ -from node.commands import cmd_shutdown_node -from node.actions import get_base_ports - -quorum_base_server, quorum_grpc_server = get_base_ports() - -for i in range(0, 5): - server_port = quorum_base_server + i - grpc_port = quorum_grpc_server + i - - cmd_shutdown_node(server_port, grpc_port) - -for i in range(0, 2): - server_port = quorum_base_server + 10 + i - grpc_port = quorum_grpc_server + 10 + i - - cmd_shutdown_node(server_port, grpc_port) +from node.commands import cmd_shutdown_node +from node.actions import get_base_ports + +quorum_base_server, quorum_grpc_server = get_base_ports() + +for i in range(0, 5): + server_port = quorum_base_server + i + grpc_port = quorum_grpc_server + i + + cmd_shutdown_node(server_port, grpc_port) + +for i in range(0, 2): + server_port = quorum_base_server + 10 + i + grpc_port = quorum_grpc_server + 10 + i + + cmd_shutdown_node(server_port, grpc_port) From 026b79ad2b6b3059ab1eeec3fc4f09ecabcf7c31 Mon Sep 17 00:00:00 2001 From: Arnab Ghose Date: Mon, 13 May 2024 10:04:32 +0530 Subject: [PATCH 027/129] feat: added test workflow --- .github/workflows/tests.yml | 93 +++++++++++++++++++++++++++++++++ tests/node/actions.py | 12 +++-- tests/node/commands.py | 26 ++++++++- tests/node/quorum.py | 7 +-- tests/scenarios/rbt_transfer.py | 10 ++-- tests/scenarios/util.py | 9 ++++ tests/shutdown.py | 5 +- 7 files changed, 142 insertions(+), 20 deletions(-) create mode 100644 .github/workflows/tests.yml create mode 100644 tests/scenarios/util.py diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml new file mode 100644 index 00000000..0f9dc3de --- /dev/null +++ b/.github/workflows/tests.yml @@ -0,0 +1,93 @@ +name: Test Workflow + +on: + pull_request: + branches: + - development + - main + +jobs: + test-linux: + name: "Test - Linux Environment" + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v4 + with: + fetch-depth: 0 + + - name: Setup Golang v1.21.9 + uses: actions/setup-go@v5 + with: + go-version: '1.21.9' + + - name: Setup Python v3.11 + uses: actions/setup-python@v5 + with: + python-version: '3.11' + + - name: Install test dependency + run: | + pip3 install requests + + - name: Run tests + run: | + cd tests && ls && python3 -u run.py + + test-macos: + name: "Test - MacOS Environment" + runs-on: macos-latest + steps: + - name: Checkout + uses: actions/checkout@v4 + with: + fetch-depth: 0 + + - name: Setup Golang v1.21.9 + uses: actions/setup-go@v5 + with: + go-version: '1.21.9' + + - name: Setup Python v3.11 + uses: actions/setup-python@v5 + with: + python-version: '3.11' + + - name: Install test dependency + run: | + pip3 install requests + + - name: MacOS install tmux + run: brew install tmux + + - name: Run tests + run: | + cd tests && ls && python3 -u run.py + + test-windows: + name: "Test - Windows Environment" + runs-on: windows-latest + steps: + - name: Checkout + uses: actions/checkout@v4 + with: + fetch-depth: 0 + + - name: Setup Golang v1.21.9 + uses: actions/setup-go@v5 + with: + go-version: '1.21.9' + + - name: Setup Python v3.11 + uses: actions/setup-python@v5 + with: + python-version: '3.11' + + - name: Install test dependency + run: | + pip3 install requests + + - name: Run tests + run: | + cd tests && ls && python3 -u run.py + diff --git a/tests/node/actions.py b/tests/node/actions.py index 9cc014e4..450be822 100644 --- a/tests/node/actions.py +++ b/tests/node/actions.py @@ -53,9 +53,10 @@ def setup_rubix_nodes(node_count: int = 0, node_prefix_str: str = "node"): # Start rubix servers loop_start_idx, loop_end_idx = 0, node_count - + offset = 4 + for i in range(loop_start_idx, loop_end_idx): - k = i if node_prefix_str == "node" else (10+i) + k = (i + offset) if node_prefix_str == "node" else (10 + i + offset) ens_server = base_ens_server + k print(f"Running server at port: {ens_server}") @@ -96,9 +97,10 @@ def create_and_register_did(node_config: dict, register_did: bool = True): config["did"] = did_id def fund_dids_with_rbt(node_config: dict, rbt_amount: int = 30): - for config in node_config.values(): - cmd_generate_rbt(config["did"], rbt_amount, config["server"], config["grpcPort"]) - print("DID ", config["did"], f" is funded with {rbt_amount} RBT") + for node, config in node_config.items(): + if node not in ["node5", "node6", "node7", "node8"]: + cmd_generate_rbt(config["did"], rbt_amount, config["server"], config["grpcPort"]) + print("DID ", config["did"], f" is funded with {rbt_amount} RBT") def fund_did_with_rbt(config: dict, rbt_amount: int = 30): output = cmd_generate_rbt(config["did"], rbt_amount, config["server"], config["grpcPort"]) diff --git a/tests/node/commands.py b/tests/node/commands.py index 8ca91ce3..4d674cc5 100644 --- a/tests/node/commands.py +++ b/tests/node/commands.py @@ -2,6 +2,8 @@ import os import re import platform +import time +import requests def is_windows_os(): os_name = platform.system() @@ -50,7 +52,6 @@ def cmd_run_rubix_servers(node_name, server_port_idx, grpc_port): cmd_string = "" if is_windows_os(): - #cmd = f".\\rubixgoplatform run -p {node_name} -n {server_port_idx} -s -testNet -grpcPort {grpc_port}" cmd_string = f"powershell -Command Start-Process -FilePath '.\\rubixgoplatform.exe' -ArgumentList 'run -p {node_name} -n {server_port_idx} -s -testNet -grpcPort {grpc_port}' -WindowStyle Hidden" else: cmd_string = f"tmux new -s {node_name} -d ./rubixgoplatform run -p {node_name} -n {server_port_idx} -s -testNet -grpcPort {grpc_port}" @@ -58,8 +59,31 @@ def cmd_run_rubix_servers(node_name, server_port_idx, grpc_port): _, code = run_command(cmd_string) if code != 0: raise Exception("Error occurred while run the command: " + cmd_string) + + print("Waiting for 60 seconds before checking if its running....") + time.sleep(60) + try: + check_if_all_nodes_are_running(server_port_idx) + except Exception as e: + raise e os.chdir("../tests") +def check_if_all_nodes_are_running(server_idx): + + base_server = 20000 + port = base_server + int(server_idx) + print(f"Check if server with ENS web server port {port} is running...") + url = f"http://localhost:{port}/api/getalldid" + try: + print(f"Sending GET request to URL: {url}") + response = requests.get(url) + if response.status_code == 200: + print(f"Server with port {port} is running successfully") + else: + raise Exception(f"Failed with Status Code: {response.status_code} | Server with port {port} is NOT running successfully") + except: + raise Exception(f"ConnectionError | Server with port {port} is NOT running successfully") + def cmd_create_did(server_port, grpc_port): os.chdir("../" + get_build_dir()) diff --git a/tests/node/quorum.py b/tests/node/quorum.py index ba5de3d3..62701bf4 100644 --- a/tests/node/quorum.py +++ b/tests/node/quorum.py @@ -13,9 +13,6 @@ def run_quorum_nodes(node_config_path, only_run_nodes, skip_adding_quorums): print("Rubix nodes are now running") if not only_run_nodes: - print("Waiting 60 seconds before fetching all node peer IDs............") - time.sleep(60) - fetch_peer_ids(node_config) print("Creation and registeration of quorum DIDs have started") @@ -45,9 +42,7 @@ def run_non_quorum_nodes(node_config_path, only_run_nodes, skip_adding_quorums): node_config = setup_rubix_nodes(2, "nodeNq") print("Non-quorum nodes are running successfully") - if not only_run_nodes: - print("Waiting 30 seconds before fetching all node peer IDs............") - time.sleep(30) + if not only_run_nodes: fetch_peer_ids(node_config) print("Creation of Non Quorum DIDs have started") diff --git a/tests/scenarios/rbt_transfer.py b/tests/scenarios/rbt_transfer.py index f8688744..315960fd 100644 --- a/tests/scenarios/rbt_transfer.py +++ b/tests/scenarios/rbt_transfer.py @@ -1,9 +1,9 @@ from node.actions import rbt_transfer, fund_did_with_rbt from helper.utils import expect_failure, expect_success +from .util import get_non_quorum_node_configs def max_decimal_place_transfer(config): - node_A_info = config["nodeNq10"] - node_B_info = config["nodeNq11"] + node_A_info, node_B_info = config["nodeNq14"], config["nodeNq15"] print("------ Test Case (FAIL) : Transferring 0.00000009 RBT from B which is more than allowed decimal places ------") @@ -13,8 +13,7 @@ def max_decimal_place_transfer(config): print("\n------ Test Case (FAIL) : Transferring 0.00000009 RBT from B which is more than allowed decimal places completed ------\n") def insufficient_balance_transfer(config): - node_A_info = config["nodeNq10"] - node_B_info = config["nodeNq11"] + node_A_info, node_B_info = config["nodeNq14"], config["nodeNq15"] print("\n------ Test Case (FAIL) : Transferring 100 RBT from A which has zero balance ------") @@ -32,8 +31,7 @@ def insufficient_balance_transfer(config): print("\n------ Test Case (FAIL) : Transferring 100 RBT from B which has insufficient balance completed ------\n") def shuttle_transfer(config): - node_A_info = config["nodeNq10"] - node_B_info = config["nodeNq11"] + node_A_info, node_B_info = config["nodeNq14"], config["nodeNq15"] print("------ Test Case (PASS): Shuttle transfer started ------\n") diff --git a/tests/scenarios/util.py b/tests/scenarios/util.py new file mode 100644 index 00000000..a851d784 --- /dev/null +++ b/tests/scenarios/util.py @@ -0,0 +1,9 @@ +def get_non_quorum_node_configs(config: dict): + sender_config = {} + receiver_config = {} + + for node in config: + sender_config = config[node] + receiver_config = config[node] + + return sender_config, receiver_config \ No newline at end of file diff --git a/tests/shutdown.py b/tests/shutdown.py index 5e9d2399..fc78cd92 100644 --- a/tests/shutdown.py +++ b/tests/shutdown.py @@ -2,14 +2,15 @@ from node.actions import get_base_ports quorum_base_server, quorum_grpc_server = get_base_ports() +offset = 4 -for i in range(0, 5): +for i in range(offset, 5 + offset): server_port = quorum_base_server + i grpc_port = quorum_grpc_server + i cmd_shutdown_node(server_port, grpc_port) -for i in range(0, 2): +for i in range(offset, 2 + offset): server_port = quorum_base_server + 10 + i grpc_port = quorum_grpc_server + 10 + i From 9e2f1bd2911d2eea6ea8d0eb8d04e5159fbbde8a Mon Sep 17 00:00:00 2001 From: Arnab Ghose Date: Wed, 15 May 2024 09:30:55 +0530 Subject: [PATCH 028/129] added dockerfile for running tests in ubuntu-amd64 environment --- tests/README.md | 14 ++++++++++++++ tests/docker/ubuntu_test.Dockerfile | 18 ++++++++++++++++++ 2 files changed, 32 insertions(+) create mode 100644 tests/docker/ubuntu_test.Dockerfile diff --git a/tests/README.md b/tests/README.md index 2d6f8ff0..e3506621 100644 --- a/tests/README.md +++ b/tests/README.md @@ -35,6 +35,20 @@ To start the test. Please NOTE that it must be run from the `tests` directory on python3 run.py ``` +## Running tests in Docker + +To run the tests in a Docker Ubuntu environment, run the following: + +1. Build the image +``` +docker build -t rubix_test_image_ubuntu --no-cache -f tests/docker/ubuntu_test.Dockerfile . +``` + +2. Run the container +``` +docker run --rm --name rubix_test_container_ubuntu rubix_test_image_ubuntu +``` + ### Flags The test script is equipped with CLI Parser. Following are the flags and their description diff --git a/tests/docker/ubuntu_test.Dockerfile b/tests/docker/ubuntu_test.Dockerfile new file mode 100644 index 00000000..8ba1dd2c --- /dev/null +++ b/tests/docker/ubuntu_test.Dockerfile @@ -0,0 +1,18 @@ +FROM amd64/ubuntu + +# Install python3 and requests dependency +RUN apt-get update && apt-get install -y python3 python3-requests wget build-essential tmux + +# Install golang 1.21 +RUN wget https://go.dev/dl/go1.21.10.linux-amd64.tar.gz +RUN tar -C /usr/local -xzf go1.21.10.linux-amd64.tar.gz +ENV PATH="/usr/local/go/bin:${PATH}" + +# Copy the tests directory +COPY . /usr/node/ + +# Change directory to test +WORKDIR /usr/node/tests + +# Run tests +CMD ["python3", "-u", "run.py"] From c6ad83edf2ea2028025ff0e6dfc250bbb60a7d50 Mon Sep 17 00:00:00 2001 From: Arnab Ghose Date: Wed, 15 May 2024 09:45:48 +0530 Subject: [PATCH 029/129] added script to collect all quorum and non-quorum logs; added step in test workflow to upload the node logs as artifacts in Github Action sessions --- .github/workflows/tests.yml | 37 ++++++++++++++++++++++++++++++++++++- tests/pack_node_logs.py | 33 +++++++++++++++++++++++++++++++++ 2 files changed, 69 insertions(+), 1 deletion(-) create mode 100644 tests/pack_node_logs.py diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 0f9dc3de..cfc33d46 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -33,6 +33,18 @@ jobs: - name: Run tests run: | cd tests && ls && python3 -u run.py + + - name: Packing Quorum and Non-Quorum node logs + if: always() + run: | + cd tests && python3 -u pack_node_logs.py + + - name: Uploading Quorum and Non-Quorum node logs as Artifacts + if: always() + uses: actions/upload-artifact@v4 + with: + name: artifact-log + path: tests/node_logs test-macos: name: "Test - MacOS Environment" @@ -64,6 +76,18 @@ jobs: run: | cd tests && ls && python3 -u run.py + - name: Packing Quorum and Non-Quorum node logs + if: always() + run: | + cd tests && python3 -u pack_node_logs.py + + - name: Uploading Quorum and Non-Quorum node logs as Artifacts + if: always() + uses: actions/upload-artifact@v4 + with: + name: artifact-log + path: tests/node_logs + test-windows: name: "Test - Windows Environment" runs-on: windows-latest @@ -90,4 +114,15 @@ jobs: - name: Run tests run: | cd tests && ls && python3 -u run.py - + + - name: Packing Quorum and Non-Quorum node logs + if: always() + run: | + cd tests && python3 -u pack_node_logs.py + + - name: Uploading Quorum and Non-Quorum node logs as Artifacts + if: always() + uses: actions/upload-artifact@v4 + with: + name: artifact-log + path: tests/node_logs diff --git a/tests/pack_node_logs.py b/tests/pack_node_logs.py new file mode 100644 index 00000000..afe56433 --- /dev/null +++ b/tests/pack_node_logs.py @@ -0,0 +1,33 @@ +# This script packs all the quorum and non-quorum node logs in `tests/node_logs` + +import os +import shutil + +def collect_logs(base_dir, output_dir): + # Ensure the output directory exists + os.makedirs(output_dir, exist_ok=True) + + # Iterate over files and directories in the build directory + for env in ['linux', 'windows', 'mac']: + env_path = os.path.join(base_dir, env) + if os.path.isdir(env_path): + for item in os.listdir(env_path): + item_path = os.path.join(env_path, item) + # Check if the directory name starts with `node`. + if os.path.isdir(item_path) and item.startswith('node'): + log_file_path = os.path.join(item_path, 'log.txt') + if os.path.exists(log_file_path): + # Rename the log file in `log__.txt` + new_log_name = f'log_{env}_{item}.txt' + new_log_path = os.path.join(output_dir, new_log_name) + # Copy the log file to the output directory + shutil.copyfile(log_file_path, new_log_path) + print(f'Copied {new_log_name} to {output_dir}') + else: + print(f'log.txt not found in {item_path}') + +if __name__ == "__main__": + base_directory = '..' # Parent directory of 'tests' where build directory is located + output_directory = './node_logs' # Directory to store collected logs + collect_logs(base_directory, output_directory) + print(f'All logs collected into {output_directory}') \ No newline at end of file From 54ae41e98a627a69359a805119109965413b8a7b Mon Sep 17 00:00:00 2001 From: Arnab Ghose Date: Wed, 15 May 2024 09:46:51 +0530 Subject: [PATCH 030/129] reduced node liveness wait time from 60 seconds to 15 seconds --- tests/node/commands.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/node/commands.py b/tests/node/commands.py index 4d674cc5..d654a0c4 100644 --- a/tests/node/commands.py +++ b/tests/node/commands.py @@ -60,8 +60,8 @@ def cmd_run_rubix_servers(node_name, server_port_idx, grpc_port): if code != 0: raise Exception("Error occurred while run the command: " + cmd_string) - print("Waiting for 60 seconds before checking if its running....") - time.sleep(60) + print("Waiting for 15 seconds before checking if its running....") + time.sleep(15) try: check_if_all_nodes_are_running(server_port_idx) except Exception as e: From 15c4a5c97cb5f002137b46e6227c5d66b13b3c43 Mon Sep 17 00:00:00 2001 From: Arnab Ghose Date: Wed, 15 May 2024 09:55:50 +0530 Subject: [PATCH 031/129] increased node liveness wait time to 40 seconds --- tests/node/commands.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/node/commands.py b/tests/node/commands.py index d654a0c4..ac633951 100644 --- a/tests/node/commands.py +++ b/tests/node/commands.py @@ -60,8 +60,8 @@ def cmd_run_rubix_servers(node_name, server_port_idx, grpc_port): if code != 0: raise Exception("Error occurred while run the command: " + cmd_string) - print("Waiting for 15 seconds before checking if its running....") - time.sleep(15) + print("Waiting for 40 seconds before checking if its running....") + time.sleep(40) try: check_if_all_nodes_are_running(server_port_idx) except Exception as e: From 8e9174b06ce623d958f30e1f6735be63f6fee3d1 Mon Sep 17 00:00:00 2001 From: Arnab Ghose Date: Wed, 15 May 2024 09:57:00 +0530 Subject: [PATCH 032/129] added OS alias in artifact name --- .github/workflows/tests.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index cfc33d46..3148c845 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -43,7 +43,7 @@ jobs: if: always() uses: actions/upload-artifact@v4 with: - name: artifact-log + name: artifact-log-linux path: tests/node_logs test-macos: @@ -85,7 +85,7 @@ jobs: if: always() uses: actions/upload-artifact@v4 with: - name: artifact-log + name: artifact-log-mac path: tests/node_logs test-windows: @@ -124,5 +124,5 @@ jobs: if: always() uses: actions/upload-artifact@v4 with: - name: artifact-log + name: artifact-log-windows path: tests/node_logs From dcf3cd3f22c27de1a7fd4e3f305621d2255c7610 Mon Sep 17 00:00:00 2001 From: Arnab Ghose Date: Wed, 15 May 2024 10:37:10 +0530 Subject: [PATCH 033/129] changed test swarm key --- tests/fixtures/testswarm.key | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/fixtures/testswarm.key b/tests/fixtures/testswarm.key index 6f0cf118..f9c579b7 100644 --- a/tests/fixtures/testswarm.key +++ b/tests/fixtures/testswarm.key @@ -1,3 +1,3 @@ /key/swarm/psk/1.0.0/ /base16/ -278b9a199c43fa84178920bd9f5cbcd69e933ddf02a8f69e47a3ea5a1705512f \ No newline at end of file +9e56c3b3d62d9f3b2a9c4a9344b8e5d02c92a2c9b5f8a2b3a4e5b8c4f6a7c5e1 \ No newline at end of file From a37bb4ac6b0e3f2e5242f573e38370e2393d14d2 Mon Sep 17 00:00:00 2001 From: Arnab Ghose Date: Wed, 15 May 2024 15:05:07 +0530 Subject: [PATCH 034/129] non quorums DIDs are now being registered for the RBT transfer transaction to happen successfully --- tests/fixtures/testswarm.key | 2 +- tests/node/actions.py | 4 ++-- tests/node/commands.py | 11 ++++++----- tests/node/quorum.py | 2 +- 4 files changed, 10 insertions(+), 9 deletions(-) diff --git a/tests/fixtures/testswarm.key b/tests/fixtures/testswarm.key index f9c579b7..6f0cf118 100644 --- a/tests/fixtures/testswarm.key +++ b/tests/fixtures/testswarm.key @@ -1,3 +1,3 @@ /key/swarm/psk/1.0.0/ /base16/ -9e56c3b3d62d9f3b2a9c4a9344b8e5d02c92a2c9b5f8a2b3a4e5b8c4f6a7c5e1 \ No newline at end of file +278b9a199c43fa84178920bd9f5cbcd69e933ddf02a8f69e47a3ea5a1705512f \ No newline at end of file diff --git a/tests/node/actions.py b/tests/node/actions.py index 450be822..a7dcdbf4 100644 --- a/tests/node/actions.py +++ b/tests/node/actions.py @@ -84,9 +84,9 @@ def fetch_peer_ids(node_config: dict): print("Fetched all Node IDs") -def create_and_register_did(node_config: dict, register_did: bool = True): +def create_and_register_did(node_config: dict, register_did: bool = True, did_type: int = 4): for config in node_config.values(): - did_id = cmd_create_did(config["server"], config["grpcPort"]) + did_id = cmd_create_did(config["server"], config["grpcPort"], did_type) print("Created DID : ", did_id) if register_did: diff --git a/tests/node/commands.py b/tests/node/commands.py index ac633951..82cb1c57 100644 --- a/tests/node/commands.py +++ b/tests/node/commands.py @@ -84,14 +84,15 @@ def check_if_all_nodes_are_running(server_idx): except: raise Exception(f"ConnectionError | Server with port {port} is NOT running successfully") -def cmd_create_did(server_port, grpc_port): +def cmd_create_did(server_port, grpc_port, did_type = 4): os.chdir("../" + get_build_dir()) - cmd_string = f"./rubixgoplatform createdid -port {server_port} -grpcPort {grpc_port}" + cmd_string = f"./rubixgoplatform createdid -port {server_port} -grpcPort {grpc_port} -didType {did_type}" if is_windows_os(): - cmd_string = f".\\rubixgoplatform createdid -port {server_port} -grpcPort {grpc_port}" + cmd_string = f".\\rubixgoplatform createdid -port {server_port} -grpcPort {grpc_port} -didType {did_type}" output, code = run_command(cmd_string, True) - + print(output) + if code != 0: raise Exception("Error occurred while run the command: " + cmd_string) @@ -112,7 +113,7 @@ def cmd_register_did(did_id, server_port, grpc_port): cmd_string = f"./rubixgoplatform registerdid -did {did_id} -port {server_port} -grpcPort {grpc_port}" if is_windows_os(): cmd_string = f".\\rubixgoplatform registerdid -did {did_id} -port {server_port} -grpcPort {grpc_port}" - output, code = run_command(cmd_string) + output, code = run_command(cmd_string, True) print(output) if code != 0: diff --git a/tests/node/quorum.py b/tests/node/quorum.py index 62701bf4..8f3e82aa 100644 --- a/tests/node/quorum.py +++ b/tests/node/quorum.py @@ -46,7 +46,7 @@ def run_non_quorum_nodes(node_config_path, only_run_nodes, skip_adding_quorums): fetch_peer_ids(node_config) print("Creation of Non Quorum DIDs have started") - create_and_register_did(node_config, False) + create_and_register_did(node_config, True) print("Non Quorum DIDs have been created") save_to_json(node_config_path, node_config) From d96cdd6aeb6093a0ffa9b7c50e1d3cb212562307 Mon Sep 17 00:00:00 2001 From: Arnab Ghose Date: Thu, 16 May 2024 17:00:42 +0530 Subject: [PATCH 035/129] added node_registry.json config to list all the node server indeces; run_non_quorum_nodes is removed --- .gitignore | 5 +- tests/config/__init__.py | 0 tests/config/node_registry.json | 4 + tests/config/utils.py | 39 +++++++++ tests/helper/utils.py | 4 +- tests/node/actions.py | 138 ++++++++++++++++---------------- tests/node/commands.py | 16 ++-- tests/node/quorum.py | 74 ++++++----------- tests/node/utils.py | 15 ++-- tests/run.py | 33 ++++---- tests/scenarios/rbt_transfer.py | 93 ++++++++++++++++----- tests/scenarios/util.py | 9 --- tests/shutdown.py | 29 +++---- 13 files changed, 261 insertions(+), 198 deletions(-) create mode 100644 tests/config/__init__.py create mode 100644 tests/config/node_registry.json create mode 100644 tests/config/utils.py delete mode 100644 tests/scenarios/util.py diff --git a/.gitignore b/.gitignore index a3f0d8f2..a06dd9d7 100644 --- a/.gitignore +++ b/.gitignore @@ -25,4 +25,7 @@ api_config.json ipfs linux/ mac/ -windows/ \ No newline at end of file +windows/ + +# used for testing purpose +!node_registry.json \ No newline at end of file diff --git a/tests/config/__init__.py b/tests/config/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/tests/config/node_registry.json b/tests/config/node_registry.json new file mode 100644 index 00000000..de13ce6b --- /dev/null +++ b/tests/config/node_registry.json @@ -0,0 +1,4 @@ +{ + "quorum": [4, 5, 6, 7, 8], + "rbt_transfer": [9, 10] +} \ No newline at end of file diff --git a/tests/config/utils.py b/tests/config/utils.py new file mode 100644 index 00000000..af10b5cb --- /dev/null +++ b/tests/config/utils.py @@ -0,0 +1,39 @@ +import json +import os + +def get_node_registry(): + current_dir = os.path.dirname(os.path.abspath(__file__)) + node_registry_path = os.path.join(current_dir, "node_registry.json") + config = load_from_config_file(node_registry_path) + + if config == {}: + raise Exception("node registry config is empty") + return config + +def load_from_config_file(config_file_path): + try: + with open(config_file_path, 'r') as file: + config_data = json.load(file) + return config_data + except FileNotFoundError as e: + return {} + except json.JSONDecodeError as e: + raise ValueError(f"Error: The file at {config_file_path} is not a valid JSON file.") from e + except Exception as e: + raise Exception(f"An unexpected error occurred: {e}") from e + +def save_to_config_file(config_file_path, config): + try: + if os.path.exists(config_file_path): + os.remove(config_file_path) + + with open(config_file_path, 'w') as f: + json.dump(config, f, indent=4) + except FileNotFoundError as e: + raise FileNotFoundError(f"Error: The file at {config_file_path} could not be found.") from e + except PermissionError as e: + raise PermissionError(f"Error: Permission denied when trying to write to {config_file_path}.") from e + except TypeError as e: # JSON serialization errors raise TypeError, not JSONDecodeError + raise TypeError(f"Error: Failed to serialize the config data to JSON.") from e + except Exception as e: + raise Exception(f"An unexpected error occurred: {e}") from e diff --git a/tests/helper/utils.py b/tests/helper/utils.py index 68d8649f..d0732faa 100644 --- a/tests/helper/utils.py +++ b/tests/helper/utils.py @@ -3,14 +3,14 @@ def wrapper(*args, **kwargs): try: func(*args, **kwargs) except: - raise Exception("The action was expected to pass, but it failed") + raise Exception("The transaction/action was expected to pass, but it failed") return wrapper def expect_failure(func): def wrapper(*args, **kwargs): try: func(*args, **kwargs) - raise Exception("The action was expected to fail, but it passed") + raise Exception("The transaction/action was expected to fail, but it passed") except: return 0 return wrapper \ No newline at end of file diff --git a/tests/node/actions.py b/tests/node/actions.py index a7dcdbf4..72dcad05 100644 --- a/tests/node/actions.py +++ b/tests/node/actions.py @@ -1,6 +1,7 @@ from .commands import cmd_run_rubix_servers, cmd_get_peer_id, cmd_create_did, cmd_register_did, \ cmd_generate_rbt, cmd_add_quorum_dids, cmd_setup_quorum_dids, cmd_rbt_transfer, get_build_dir -from .utils import get_node_name_from_idx, save_to_json +from .utils import get_node_name_from_idx, get_did_by_alias +from config.utils import save_to_config_file, get_node_registry def add_quorums(node_config: dict): for config in node_config.values(): @@ -9,106 +10,101 @@ def add_quorums(node_config: dict): config["grpcPort"] ) -def setup_quorums(node_config: dict): - for config in node_config.values(): +def setup_quorums(node_config: dict, node_did_alias_map: dict): + for node, config in node_config.items(): + did = get_did_by_alias(config, node_did_alias_map[node]) cmd_setup_quorum_dids( - config["did"], + did, config["server"], config["grpcPort"] ) -def quorum_config(node_config: dict, skip_adding_quorums: bool = False, create_quorum_list: bool = False): +def quorum_config(node_config: dict, node_did_alias_map: dict, skip_adding_quorums: bool = False): # Prepare quorumlist.json quorum_list = [] - if create_quorum_list: - for config in node_config.values(): + build_dir = get_build_dir() + quorum_list_file_path = f"../{build_dir}/quorumlist.json" + + if skip_adding_quorums: + setup_quorums(node_config, node_did_alias_map) + else: + for node, config in node_config.items(): + did = get_did_by_alias(config, node_did_alias_map[node]) + print("got the didby alias: ", did) quorum_info = { "type": 2, - "address": config["peerId"] + "." + config["did"] + "address": config["peerId"] + "." + did } - build_dir = get_build_dir() - quorum_list_file_path = f"../{build_dir}/quorumlist.json" quorum_list.append(quorum_info) - save_to_json(quorum_list_file_path, quorum_list) + save_to_config_file(quorum_list_file_path, quorum_list) - # # add quorums - if not skip_adding_quorums: add_quorums(node_config) - setup_quorums(node_config) + setup_quorums(node_config, node_did_alias_map) -def get_base_ports(): - base_ens_server = 20000 - base_grpc_port = 10500 +def setup_rubix_nodes(node_registry_config_key): + if node_registry_config_key == "": + raise Exception("a key is needed to fetch node_registry.json config") + + node_registry = get_node_registry() + if not node_registry_config_key in node_registry: + raise Exception(f"config key {node_registry_config_key} not found in node_registry.json config") - return base_ens_server, base_grpc_port + node_indices = node_registry[node_registry_config_key] + + if not isinstance(node_indices, list): + raise Exception(f"the correspoding value for {node_registry_config_key} in node_registry.json must of List type") + + if len(node_indices) == 0: + raise Exception(f"no indices found for {node_registry_config_key} in node_registry.json, provide at least one index") -def setup_rubix_nodes(node_count: int = 0, node_prefix_str: str = "node"): - base_ens_server, base_grpc_port = get_base_ports() - node_config = {} - # Start rubix servers - loop_start_idx, loop_end_idx = 0, node_count - offset = 4 - - for i in range(loop_start_idx, loop_end_idx): - k = (i + offset) if node_prefix_str == "node" else (10 + i + offset) - - ens_server = base_ens_server + k - print(f"Running server at port: {ens_server}") - grpc_port = base_grpc_port + k - - node_name = get_node_name_from_idx(k, node_prefix_str) - - cmd_run_rubix_servers(node_name, k, grpc_port) - - node_config[node_name] = { - "did": "", - "server": ens_server, - "grpcPort": grpc_port, + for idx in node_indices: + node_name = "node" + str(idx) + node_server, grpc_server = cmd_run_rubix_servers(node_name, idx) + + cfg = { + "dids": {}, + "server": node_server, + "grpcPort": grpc_server, "peerId": "" } - return node_config - + fetch_peer_id(cfg) + node_config[node_name] = cfg -def fetch_peer_ids(node_config: dict): - print("Fetching Node IDs........") - for config in node_config.values(): - peer_id = cmd_get_peer_id(config["server"], config["grpcPort"]) - config["peerId"] = peer_id - print("Fetched all Node IDs") + return node_config +def fetch_peer_id(config): + peer_id = cmd_get_peer_id(config["server"], config["grpcPort"]) + config["peerId"] = peer_id -def create_and_register_did(node_config: dict, register_did: bool = True, did_type: int = 4): - for config in node_config.values(): - did_id = cmd_create_did(config["server"], config["grpcPort"], did_type) - print("Created DID : ", did_id) - - if register_did: - print(f"Registering DID: {did_id}") - cmd_register_did(did_id, config["server"], config["grpcPort"]) - print("DID is registered successfully\n") +def create_and_register_did(config: dict, did_alias: str, did_type: int = 4, register_did: bool = True): + did = cmd_create_did(config["server"], config["grpcPort"], did_type) + print(f"DID {did} has been created successfully") - config["did"] = did_id + config["dids"] = { + did_alias: did + } -def fund_dids_with_rbt(node_config: dict, rbt_amount: int = 30): - for node, config in node_config.items(): - if node not in ["node5", "node6", "node7", "node8"]: - cmd_generate_rbt(config["did"], rbt_amount, config["server"], config["grpcPort"]) - print("DID ", config["did"], f" is funded with {rbt_amount} RBT") + if register_did: + cmd_register_did(did, config["server"], config["grpcPort"]) + print(f"DID {did} has been registered successfully") -def fund_did_with_rbt(config: dict, rbt_amount: int = 30): - output = cmd_generate_rbt(config["did"], rbt_amount, config["server"], config["grpcPort"]) - print(output) - return output + return did -def rbt_transfer(config_sender: dict, config_receiver: dict, transfer_rbt_amount: int): - sender_address = config_sender["peerId"] + "." + config_sender["did"] - receiver_address = config_receiver["peerId"] + "." + config_receiver["did"] +def fund_did_with_rbt(node_config: dict, did: str, rbt_amount: int = 70): + cmd_generate_rbt(did, rbt_amount, node_config["server"], node_config["grpcPort"]) + print("DID ", did, f" is funded with {rbt_amount} RBT") - cmd_rbt_transfer(sender_address, receiver_address, transfer_rbt_amount, config_sender["server"], config_sender["grpcPort"]) \ No newline at end of file +def rbt_transfer( + sender_address: str, + receiver_address: str, + transfer_rbt: float, + sender_server_port: int, + sender_grpc_port: int): + cmd_rbt_transfer(sender_address, receiver_address, transfer_rbt, sender_server_port, sender_grpc_port) diff --git a/tests/node/commands.py b/tests/node/commands.py index 82cb1c57..999f316c 100644 --- a/tests/node/commands.py +++ b/tests/node/commands.py @@ -4,6 +4,7 @@ import platform import time import requests +from .utils import get_base_ports def is_windows_os(): os_name = platform.system() @@ -47,9 +48,13 @@ def run_command(cmd_string, is_output_from_stderr=False): else: return output, code -def cmd_run_rubix_servers(node_name, server_port_idx, grpc_port): +def cmd_run_rubix_servers(node_name, server_port_idx): os.chdir("../" + get_build_dir()) + base_node_server, base_grpc_port = get_base_ports() + grpc_port = base_grpc_port + server_port_idx + node_server = base_node_server + server_port_idx + cmd_string = "" if is_windows_os(): cmd_string = f"powershell -Command Start-Process -FilePath '.\\rubixgoplatform.exe' -ArgumentList 'run -p {node_name} -n {server_port_idx} -s -testNet -grpcPort {grpc_port}' -WindowStyle Hidden" @@ -63,14 +68,15 @@ def cmd_run_rubix_servers(node_name, server_port_idx, grpc_port): print("Waiting for 40 seconds before checking if its running....") time.sleep(40) try: - check_if_all_nodes_are_running(server_port_idx) + check_if_nodes_is_running(server_port_idx) except Exception as e: raise e + os.chdir("../tests") + return node_server, grpc_port -def check_if_all_nodes_are_running(server_idx): - - base_server = 20000 +def check_if_nodes_is_running(server_idx): + base_server, _ = get_base_ports() port = base_server + int(server_idx) print(f"Check if server with ENS web server port {port} is running...") url = f"http://localhost:{port}/api/getalldid" diff --git a/tests/node/quorum.py b/tests/node/quorum.py index 8f3e82aa..cb65ccbd 100644 --- a/tests/node/quorum.py +++ b/tests/node/quorum.py @@ -1,62 +1,40 @@ import pprint import time -from .actions import setup_rubix_nodes, fetch_peer_ids, create_and_register_did, \ - fund_dids_with_rbt, quorum_config -from .utils import save_to_json +from .actions import setup_rubix_nodes, create_and_register_did, \ + fund_did_with_rbt, quorum_config +from config.utils import save_to_config_file, load_from_config_file -def run_quorum_nodes(node_config_path, only_run_nodes, skip_adding_quorums): - node_config_path = "./quorum_config.json" - - print("Running Rubix nodes......") - node_config = setup_rubix_nodes(5) - print("Rubix nodes are now running") +QUORUM_CONFIG_PATH = "./quorum_config.json" - if not only_run_nodes: - fetch_peer_ids(node_config) - - print("Creation and registeration of quorum DIDs have started") - create_and_register_did(node_config) - print("All quorum DIDs have been registered") - - print("Initiating funding of these quorum DIDs") - fund_dids_with_rbt(node_config) - print("All Quorum DIDs have been funded") - - save_to_json(node_config_path, node_config) - - print("Setting up quorums and saving information about them to quorumlist.json") - quorum_config(node_config, skip_adding_quorums=skip_adding_quorums, create_quorum_list=True) - - pprint.pp(node_config) - print("Quorums have been configured") - else: - quorum_config(node_config, skip_adding_quorums=True, create_quorum_list=False) +def run_quorum_nodes(only_run_nodes, skip_adding_quorums): + print("Running Rubix Quorum nodes......") + node_registry_key = "quorum" + node_config = setup_rubix_nodes(node_registry_key) + print("Rubix Quorum nodes are now running") - return node_config + if not only_run_nodes: + did_alias = "did_quorum" + node_did_alias_map = {} -def run_non_quorum_nodes(node_config_path, only_run_nodes, skip_adding_quorums): - node_config_path = "./non_quorum_config.json" + print("Creating, Registering and Funding Quorum DIDs\n") + for node, config in node_config.items(): + did = create_and_register_did(config, did_alias) - print("Running non-quorum nodes...") - node_config = setup_rubix_nodes(2, "nodeNq") - print("Non-quorum nodes are running successfully") + fund_did_with_rbt(config, did) - if not only_run_nodes: - fetch_peer_ids(node_config) + # Selecting DIDs for quorum setup + node_did_alias_map[node] = did_alias + save_to_config_file(QUORUM_CONFIG_PATH, node_config) + print("\nquorum_config.json is created") - print("Creation of Non Quorum DIDs have started") - create_and_register_did(node_config, True) - print("Non Quorum DIDs have been created") - - save_to_json(node_config_path, node_config) - - print("Adding and setting up quorum config") - quorum_config(node_config, skip_adding_quorums=skip_adding_quorums, create_quorum_list=False) + print("Setting up quorums and saving the info in quorumlist.json") + quorum_config(node_config, node_did_alias_map, skip_adding_quorums=skip_adding_quorums) pprint.pp(node_config) - print("Non Quorum nodes have been configured") + print("Quorums have been configured") else: - quorum_config(node_config, skip_adding_quorums=True, create_quorum_list=False) + quorum_config(node_config, node_did_alias_map, skip_adding_quorums=True) - return node_config \ No newline at end of file +def get_quorum_config(): + return load_from_config_file(QUORUM_CONFIG_PATH) diff --git a/tests/node/utils.py b/tests/node/utils.py index a30cfa47..668c1d10 100644 --- a/tests/node/utils.py +++ b/tests/node/utils.py @@ -7,10 +7,11 @@ def get_node_name_from_idx(idx, prefix_string: str = "node"): return prefix_string + str(idx) -def save_to_json(filepath, obj): - # Check if file exists. If yes, then remove it - if os.path.exists(filepath): - os.remove(filepath) - - with open(filepath, 'w') as f: - json.dump(obj, f, indent=4) +def get_base_ports(): + base_ens_server = 20000 + base_grpc_port = 10500 + + return base_ens_server, base_grpc_port + +def get_did_by_alias(node_config, alias): + return node_config["dids"][alias] \ No newline at end of file diff --git a/tests/run.py b/tests/run.py index 6dbaf35a..af5c115d 100644 --- a/tests/run.py +++ b/tests/run.py @@ -4,12 +4,13 @@ import requests import argparse from node.commands import run_command -from node.quorum import run_quorum_nodes, run_non_quorum_nodes -from scenarios.rbt_transfer import * +from node.quorum import run_quorum_nodes + +from scenarios import ( + rbt_transfer +) IPFS_KUBO_VERSION = "v0.21.0" -QUORUM_CONFIG_FILE = "./quorum_config.json" -NON_QUORUM_CONFIG_FILE = "./non_quorum_config.json" def get_os_info(): os_name = platform.system() @@ -120,10 +121,7 @@ def cli(): parser.add_argument("--run_tests_only", action=argparse.BooleanOptionalAction, help="only proceed with running tests") return parser.parse_args() - if __name__=='__main__': - os.chdir("../") - args = cli() skip_prerequisite = args.skip_prerequisite run_nodes_only = args.run_nodes_only @@ -138,6 +136,7 @@ def cli(): exit(1) if not skip_prerequisite: + os.chdir("../") print(f"Building Rubix binary for {os_name}\n") build_command = "" if os_name == "Linux": @@ -154,21 +153,17 @@ def cli(): else: print("\nBuild successful\n") - download_ipfs_binary(os_name, IPFS_KUBO_VERSION, build_folder) copy_fixtures_to_build_dir(build_folder) os.chdir("./tests") - run_quorum_nodes(QUORUM_CONFIG_FILE, run_nodes_only, skip_adding_quorums=skip_adding_quorums) + run_quorum_nodes(run_nodes_only, skip_adding_quorums=skip_adding_quorums) - non_quorum_node_config = run_non_quorum_nodes(NON_QUORUM_CONFIG_FILE, run_nodes_only, skip_adding_quorums=skip_adding_quorums) - - # Run RBT Transfer related tests - rbt_transfer_test_list = [ - shuttle_transfer, - insufficient_balance_transfer, - max_decimal_place_transfer + # It will carry list of Python files containing the function `run()` + # that consists of logic to run all the necessary tests + modules = [ + rbt_transfer ] - for testFn in rbt_transfer_test_list: - testFn(non_quorum_node_config) - + + for module in modules: + module.run() diff --git a/tests/scenarios/rbt_transfer.py b/tests/scenarios/rbt_transfer.py index 315960fd..7f5c2da0 100644 --- a/tests/scenarios/rbt_transfer.py +++ b/tests/scenarios/rbt_transfer.py @@ -1,82 +1,135 @@ -from node.actions import rbt_transfer, fund_did_with_rbt +from node.actions import rbt_transfer, fund_did_with_rbt, setup_rubix_nodes, \ + create_and_register_did, add_quorums +from node.utils import get_did_by_alias +from config.utils import save_to_config_file, load_from_config_file from helper.utils import expect_failure, expect_success -from .util import get_non_quorum_node_configs + +__node_config_path = "./rbt_transfer_config.json" + +def setup(): + print("Setting up test.....") + print("Configuring and running node9 and node10...") + + node_config = setup_rubix_nodes("rbt_transfer") + + config_A = node_config["node9"] + config_B = node_config["node10"] + + create_and_register_did(config_A, "did_a") + create_and_register_did(config_B, "did_b") + + save_to_config_file(__node_config_path, node_config) + + print("Adding quorums") + add_quorums(node_config) + + print("Setup Done\n") + return node_config + +def run(skip_setup: bool = False): + print("\n----------- 1. Running Tests related to RBT Transfer -----------\n") + node_config = {} + + # In some cases, we may wish to run tests for an existing test configuration + # where the nodes are running already. If skip_setup is True, the setup steps + # are skipped and we proceed to directly run the test cases and load the config + # from the config file + if not skip_setup: + node_config = setup() + else: + node_config = load_from_config_file(__node_config_path) + + shuttle_transfer(node_config) + insufficient_balance_transfer(node_config) + max_decimal_place_transfer(node_config) + + print("\n-------------- Tests Completed -------------------\n") def max_decimal_place_transfer(config): - node_A_info, node_B_info = config["nodeNq14"], config["nodeNq15"] + node_A_info, node_B_info = config["node9"], config["node10"] + server_port_B, grpc_port_B = node_B_info["server"], node_B_info["grpcPort"] + did_A, did_B = get_did_by_alias(node_A_info, "did_a"), get_did_by_alias(node_B_info, "did_b") + address_A, address_B = node_A_info["peerId"]+"."+did_A, node_B_info["peerId"]+"."+did_B print("------ Test Case (FAIL) : Transferring 0.00000009 RBT from B which is more than allowed decimal places ------") print("\nTransferring 0.00000009 RBT from B to A....") - expect_failure(rbt_transfer)(node_B_info, node_A_info, 0.00000009) + expect_failure(rbt_transfer)(address_B, address_A, 0.00000009, server_port_B, grpc_port_B) print("\n------ Test Case (FAIL) : Transferring 0.00000009 RBT from B which is more than allowed decimal places completed ------\n") def insufficient_balance_transfer(config): - node_A_info, node_B_info = config["nodeNq14"], config["nodeNq15"] + node_A_info, node_B_info = config["node9"], config["node10"] + server_port_A, grpc_port_A = node_A_info["server"], node_A_info["grpcPort"] + server_port_B, grpc_port_B = node_B_info["server"], node_B_info["grpcPort"] + did_A, did_B = get_did_by_alias(node_A_info, "did_a"), get_did_by_alias(node_B_info, "did_b") + address_A, address_B = node_A_info["peerId"]+"."+did_A, node_B_info["peerId"]+"."+did_B print("\n------ Test Case (FAIL) : Transferring 100 RBT from A which has zero balance ------") print("\nTransferring 100 RBT from A to B....") - expect_failure(rbt_transfer)(node_A_info, node_B_info, 100) + expect_failure(rbt_transfer)(address_A, address_B, 100, server_port_A, grpc_port_A) print("\n------ Test Case (FAIL) : Transferring 100 RBT from A which has zero balance completed ------\n") - print("\n------ Test Case (FAIL) : Transferring 100 RBT from B which has insufficient balance ------") print("\nTransferring 100 RBT from B to A....") - expect_failure(rbt_transfer)(node_B_info, node_A_info, 100) + expect_failure(rbt_transfer)(address_B, address_A, 0.25, server_port_B, grpc_port_B) print("\n------ Test Case (FAIL) : Transferring 100 RBT from B which has insufficient balance completed ------\n") def shuttle_transfer(config): - node_A_info, node_B_info = config["nodeNq14"], config["nodeNq15"] + node_A_info, node_B_info = config["node9"], config["node10"] + server_port_A, grpc_port_A = node_A_info["server"], node_A_info["grpcPort"] + server_port_B, grpc_port_B = node_B_info["server"], node_B_info["grpcPort"] + did_A, did_B = get_did_by_alias(node_A_info, "did_a"), get_did_by_alias(node_B_info, "did_b") + address_A, address_B = node_A_info["peerId"]+"."+did_A, node_B_info["peerId"]+"."+did_B print("------ Test Case (PASS): Shuttle transfer started ------\n") print("\n1. Generating 2 whole RBT for A") - expect_success(fund_did_with_rbt)(node_A_info, 2) + expect_success(fund_did_with_rbt)(node_A_info, did_A, 2) print("Funded node A with 2 RBT") print("\n2. Transferring 0.5 RBT from A to B....") - expect_success(rbt_transfer)(node_A_info, node_B_info, 0.5) + expect_success(rbt_transfer)(address_A, address_B, 0.5, server_port_A, grpc_port_A) print("Transferred 0.5 RBT from A to B") print("\n3. Transferring 1.499 RBT from A to B....") - expect_success(rbt_transfer)(node_A_info, node_B_info, 1.499) + expect_success(rbt_transfer)(address_A, address_B, 1.499, server_port_A, grpc_port_A) print("Transferred 1.499 RBT from A to B") print("\n4. Transferring 0.25 RBT from B to A....") - expect_success(rbt_transfer)(node_B_info, node_A_info, 0.25) + expect_success(rbt_transfer)(address_B, address_A, 0.25, server_port_B, grpc_port_B) print("Transferred 0.25 RBT from B to A") print("\n5. Transferring 0.25 RBT from B to A....") - expect_success(rbt_transfer)(node_B_info, node_A_info, 0.25) + expect_success(rbt_transfer)(address_B, address_A, 0.25, server_port_B, grpc_port_B) print("Transferred 0.25 RBT from B to A") print("\n6. Transferring 0.25 RBT from B to A....") - expect_success(rbt_transfer)(node_B_info, node_A_info, 0.25) + expect_success(rbt_transfer)(address_B, address_A, 0.25, server_port_B, grpc_port_B) print("Transferred 0.25 RBT from B to A") print("\n7. Transferring 0.25 RBT from B to A....") - expect_success(rbt_transfer)(node_B_info, node_A_info, 0.25) + expect_success(rbt_transfer)(address_B, address_A, 0.25, server_port_B, grpc_port_B) print("Transferred 0.25 RBT from B to A") print("\n8. Transferring 1 RBT from A to B....") - expect_success(rbt_transfer)(node_A_info, node_B_info, 1) + expect_success(rbt_transfer)(address_A, address_B, 1, server_port_A, grpc_port_A) print("Transferred 1 RBT from A to B") print("\n9. Generating 2 whole RBT for A") - expect_success(fund_did_with_rbt)(node_A_info, 2) + expect_success(fund_did_with_rbt)(node_A_info, did_A, 2) print("Funded node A with 2 RBT") print("\n10. Transferring 2 RBT from A to B....") - expect_success(rbt_transfer)(node_A_info, node_B_info, 2) + expect_success(rbt_transfer)(address_A, address_B, 2, server_port_A, grpc_port_A) print("Transferred 2 RBT from A to B") print("\n11. Transferring 0.001 RBT from A to B....") - expect_success(rbt_transfer)(node_A_info, node_B_info, 0.001) + expect_success(rbt_transfer)(address_A, address_B, 0.001, server_port_A, grpc_port_A) print("Transferred 0.001 RBT from A to B") print("\n------ Test Case (PASS): Shuttle transfer completed ------\n") diff --git a/tests/scenarios/util.py b/tests/scenarios/util.py deleted file mode 100644 index a851d784..00000000 --- a/tests/scenarios/util.py +++ /dev/null @@ -1,9 +0,0 @@ -def get_non_quorum_node_configs(config: dict): - sender_config = {} - receiver_config = {} - - for node in config: - sender_config = config[node] - receiver_config = config[node] - - return sender_config, receiver_config \ No newline at end of file diff --git a/tests/shutdown.py b/tests/shutdown.py index fc78cd92..8d96c103 100644 --- a/tests/shutdown.py +++ b/tests/shutdown.py @@ -1,17 +1,14 @@ from node.commands import cmd_shutdown_node -from node.actions import get_base_ports - -quorum_base_server, quorum_grpc_server = get_base_ports() -offset = 4 - -for i in range(offset, 5 + offset): - server_port = quorum_base_server + i - grpc_port = quorum_grpc_server + i - - cmd_shutdown_node(server_port, grpc_port) - -for i in range(offset, 2 + offset): - server_port = quorum_base_server + 10 + i - grpc_port = quorum_grpc_server + 10 + i - - cmd_shutdown_node(server_port, grpc_port) +from node.utils import get_base_ports +from config.utils import get_node_registry + +if __name__=='__main__': + base_node_server, base_grpc_server = get_base_ports() + node_registry_config = get_node_registry() + + for indices in node_registry_config.values(): + for i in indices: + server_port = base_node_server + i + grpc_port = base_grpc_server + i + print(f"Shutting down server running at {server_port}") + cmd_shutdown_node(server_port, grpc_port) From 8eb6e5ca94540e42dbad47f2be2be42941bd9217 Mon Sep 17 00:00:00 2001 From: Arnab Ghose Date: Thu, 16 May 2024 17:11:29 +0530 Subject: [PATCH 036/129] renamed test workflow artifiacts name --- .github/workflows/tests.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 3148c845..cc2a882f 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -43,7 +43,7 @@ jobs: if: always() uses: actions/upload-artifact@v4 with: - name: artifact-log-linux + name: node-logs-linux path: tests/node_logs test-macos: @@ -85,7 +85,7 @@ jobs: if: always() uses: actions/upload-artifact@v4 with: - name: artifact-log-mac + name: node-logs-macos path: tests/node_logs test-windows: @@ -124,5 +124,5 @@ jobs: if: always() uses: actions/upload-artifact@v4 with: - name: artifact-log-windows + name: node-logs-windows path: tests/node_logs From c425be1decf99a2ea1a690788fb44d3ac1ddbf3b Mon Sep 17 00:00:00 2001 From: Arnab Ghose Date: Fri, 17 May 2024 09:56:07 +0530 Subject: [PATCH 037/129] added test scenario for BIP39 and NLSS transfers --- tests/README.md | 10 ++++ tests/config/node_registry.json | 3 +- tests/run.py | 6 +- tests/scenarios/bip39_nlss_test.py | 89 ++++++++++++++++++++++++++++++ 4 files changed, 105 insertions(+), 3 deletions(-) create mode 100644 tests/scenarios/bip39_nlss_test.py diff --git a/tests/README.md b/tests/README.md index e3506621..c963fb15 100644 --- a/tests/README.md +++ b/tests/README.md @@ -20,6 +20,16 @@ The test script covers the following RBT Transfer scenarios: 3. Transferring 0.00000009 RBT from B which is more than allowed decimal places (Failure Case) +4. Transferring whole, part and mix RBT from NLSS DID to BIP39 DID
+ 4.1 Transfer 1 RBT from NLSS DID to BIP39 DID
+ 4.2 Transfer 1.5 RBT from NLSS DID to BIP39 DID
+ 4.3 Transfer 0.5 RBT from NLSS DID to BIP39 DID
+ +5. Transferring whole, part and mix RBT from BIP39 DID to NLSS DID
+ 5.1 Transfer 0.5 RBT from NLSS DID to BIP39 DID
+ 5.2 Transfer 1.5 RBT from NLSS DID to BIP39 DID
+ 5.3 Transfer 1 RBT from NLSS DID to BIP39 DID
+ ## Prerequisites - Python 3.10+ ([Install Ref](https://www.python.org/downloads/)) diff --git a/tests/config/node_registry.json b/tests/config/node_registry.json index de13ce6b..08c4e27b 100644 --- a/tests/config/node_registry.json +++ b/tests/config/node_registry.json @@ -1,4 +1,5 @@ { "quorum": [4, 5, 6, 7, 8], - "rbt_transfer": [9, 10] + "rbt_transfer": [9, 10], + "bip39_nlss": [11, 12] } \ No newline at end of file diff --git a/tests/run.py b/tests/run.py index af5c115d..f0d78c0e 100644 --- a/tests/run.py +++ b/tests/run.py @@ -7,7 +7,8 @@ from node.quorum import run_quorum_nodes from scenarios import ( - rbt_transfer + rbt_transfer, + bip39_nlss_test ) IPFS_KUBO_VERSION = "v0.21.0" @@ -162,7 +163,8 @@ def cli(): # It will carry list of Python files containing the function `run()` # that consists of logic to run all the necessary tests modules = [ - rbt_transfer + rbt_transfer, + bip39_nlss_test ] for module in modules: diff --git a/tests/scenarios/bip39_nlss_test.py b/tests/scenarios/bip39_nlss_test.py new file mode 100644 index 00000000..74aa300c --- /dev/null +++ b/tests/scenarios/bip39_nlss_test.py @@ -0,0 +1,89 @@ +from node.actions import rbt_transfer, fund_did_with_rbt, setup_rubix_nodes, \ + create_and_register_did, add_quorums +from node.utils import get_did_by_alias +from config.utils import save_to_config_file, load_from_config_file +from helper.utils import expect_failure, expect_success + +__node_config_path = "./bip39_nlss_config.json" + +def setup(): + print("Setting up test.....") + print("Configuring and running node11 and node12...") + + node_config = setup_rubix_nodes("bip39_nlss") + + config_bip39 = node_config["node11"] + config_nlss = node_config["node12"] + + create_and_register_did(config_bip39, "bip39_1", did_type=4) + + + create_and_register_did(config_nlss, "nlss_1", did_type=0) + + save_to_config_file(__node_config_path, node_config) + + print("Adding quorums") + add_quorums(node_config) + + print("Setup Done\n") + return node_config + +def run(skip_setup: bool = False): + print("\n----------- 2. Running Tests related to RBT Transfer between BIP39 and NLSS dids -----------\n") + node_config = {} + + if not skip_setup: + node_config = setup() + else: + node_config = load_from_config_file(__node_config_path) + + nlss_to_bip39(node_config) + bip39_to_nlss(node_config) + print("\n-------------- Tests Completed -------------------\n") + +def nlss_to_bip39(node_config): + node_bip39, node_nlss = node_config["node11"], node_config["node12"] + server_port_nlss, grpc_port_nlss = node_nlss["server"], node_nlss["grpcPort"] + did_bip39, did_nlss = get_did_by_alias(node_bip39, "bip39_1"), get_did_by_alias(node_nlss, "nlss_1") + address_bip39, address_nlss = node_bip39["peerId"]+"."+did_bip39, node_nlss["peerId"]+"."+did_nlss + + print("------ Test Case (PASS): Transferring whole, part and mix RBT from NLSS DID to BIP39 DID ------\n") + + print("\n1. Generating 3 RBT for NLSS DID") + expect_success(fund_did_with_rbt)(node_nlss, did_nlss, 3) + print("Funded NLSS DID with 3 RBT") + + print("\n2. Transferring 1 RBT from NLSS DID to BIP39 DID....") + expect_success(rbt_transfer)(address_nlss, address_bip39, 1, server_port_nlss, grpc_port_nlss) + print("Transferred 1 RBT from NLSS DID to BIP39 DID") + + print("\n3. Transferring 1.5 RBT from NLSS DID to BIP39 DID....") + expect_success(rbt_transfer)(address_nlss, address_bip39, 1.5, server_port_nlss, grpc_port_nlss) + print("Transferred 1.5 RBT from NLSS DID to BIP39 DID") + + print("\n4. Transferring 0.5 RBT from NLSS DID to BIP39 DID....") + expect_success(rbt_transfer)(address_nlss, address_bip39, 0.5, server_port_nlss, grpc_port_nlss) + print("Transferred 0.5 RBT from NLSS DID to BIP39 DID") + + print("\n------ Test Case (PASS): Transferring whole, part and mix RBT from NLSS DID to BIP39 DID completed ------\n") + +def bip39_to_nlss(node_config): + node_bip39, node_nlss = node_config["node11"], node_config["node12"] + server_port_bip39, grpc_port_bip39 = node_bip39["server"], node_bip39["grpcPort"] + did_bip39, did_nlss = get_did_by_alias(node_bip39, "bip39_1"), get_did_by_alias(node_nlss, "nlss_1") + address_bip39, address_nlss = node_bip39["peerId"]+"."+did_bip39, node_nlss["peerId"]+"."+did_nlss + + print("------ Test Case (PASS): Transferring whole, part and mix RBT from BIP39 DID to NLSS DID ------\n") + + print("\n4. Transferring 0.5 RBT from BIP39 DID to NLSS DID....") + expect_success(rbt_transfer)(address_bip39, address_nlss, 0.5, server_port_bip39, grpc_port_bip39) + print("Transferred 0.5 RBT from BIP39 DID to NLSS DID") + + print("\n3. Transferring 1.5 RBT from BIP39 DID to NLSS DID....") + expect_success(rbt_transfer)(address_bip39, address_nlss, 1.5, server_port_bip39, grpc_port_bip39) + print("Transferred 1.5 RBT from BIP39 DID to NLSS DID") + + print("\n2. Transferring 1 RBT from BIP39 DID to NLSS DID....") + expect_success(rbt_transfer)(address_bip39, address_nlss, 1, server_port_bip39, grpc_port_bip39) + print("Transferred 1 RBT from BIP39 DID to NLSS DID") + From 70df360a12756cdce2d467a44664713c171d5e59 Mon Sep 17 00:00:00 2001 From: Arnab Ghose Date: Fri, 17 May 2024 11:41:03 +0530 Subject: [PATCH 038/129] added entry for .sh file extension --- tests/README.md | 42 +++++++++++++++++++++--------------------- 1 file changed, 21 insertions(+), 21 deletions(-) diff --git a/tests/README.md b/tests/README.md index c963fb15..bff954d1 100644 --- a/tests/README.md +++ b/tests/README.md @@ -4,31 +4,31 @@ The test script does the complete setup by building the rubix node based on the The test script covers the following RBT Transfer scenarios: -1. Shuttle Transfer (Success Case)
- 1.1 Generate 2 whole RBT for A
- 1.2 Transfer 0.5 from A to B
- 1.3 Transfer 1.499 from A to B
- 1.4 (Transfer 0.25 from B to A) * 4
- 1.5 Transfer 1 RBT from A to B
- 1.6 Generate 2 whole RBT for A
- 1.7 Transfer 2 RBT from A to B
- 1.8 Transfer 0.001 from A to B
- -2. Insufficient Balance Transfer (Failure Case)
- 2.1 Transferring 100 RBT from A which has zero balance
- 2.2 Transferring 100 RBT from B which has insufficient balance
+1. Shuttle Transfer (Success Case) + 1.1 Generate 2 whole RBT for A + 1.2 Transfer 0.5 from A to B + 1.3 Transfer 1.499 from A to B + 1.4 (Transfer 0.25 from B to A) * 4 + 1.5 Transfer 1 RBT from A to B + 1.6 Generate 2 whole RBT for A + 1.7 Transfer 2 RBT from A to B + 1.8 Transfer 0.001 from A to B + +2. Insufficient Balance Transfer (Failure Case) + 2.1 Transferring 100 RBT from A which has zero balance + 2.2 Transferring 100 RBT from B which has insufficient balance 3. Transferring 0.00000009 RBT from B which is more than allowed decimal places (Failure Case) -4. Transferring whole, part and mix RBT from NLSS DID to BIP39 DID
- 4.1 Transfer 1 RBT from NLSS DID to BIP39 DID
- 4.2 Transfer 1.5 RBT from NLSS DID to BIP39 DID
- 4.3 Transfer 0.5 RBT from NLSS DID to BIP39 DID
+4. Transferring whole, part and mix RBT from NLSS DID to BIP39 DID + 4.1 Transfer 1 RBT from NLSS DID to BIP39 DID + 4.2 Transfer 1.5 RBT from NLSS DID to BIP39 DID + 4.3 Transfer 0.5 RBT from NLSS DID to BIP39 DID -5. Transferring whole, part and mix RBT from BIP39 DID to NLSS DID
- 5.1 Transfer 0.5 RBT from NLSS DID to BIP39 DID
- 5.2 Transfer 1.5 RBT from NLSS DID to BIP39 DID
- 5.3 Transfer 1 RBT from NLSS DID to BIP39 DID
+5. Transferring whole, part and mix RBT from BIP39 DID to NLSS DID + 5.1 Transfer 0.5 RBT from NLSS DID to BIP39 DID + 5.2 Transfer 1.5 RBT from NLSS DID to BIP39 DID + 5.3 Transfer 1 RBT from NLSS DID to BIP39 DID ## Prerequisites From 460c0f688b437f09bf69cc3b5979e2a5e02bcf23 Mon Sep 17 00:00:00 2001 From: Arnab Ghose Date: Mon, 20 May 2024 12:10:49 +0530 Subject: [PATCH 039/129] created three swarm keys for each os environment --- tests/fixtures/testswarm.key | 3 --- tests/fixtures/testswarm_linux.key | 3 +++ tests/fixtures/testswarm_mac.key | 3 +++ tests/fixtures/testswarm_windows.key | 3 +++ tests/run.py | 6 +++--- 5 files changed, 12 insertions(+), 6 deletions(-) delete mode 100644 tests/fixtures/testswarm.key create mode 100644 tests/fixtures/testswarm_linux.key create mode 100644 tests/fixtures/testswarm_mac.key create mode 100644 tests/fixtures/testswarm_windows.key diff --git a/tests/fixtures/testswarm.key b/tests/fixtures/testswarm.key deleted file mode 100644 index 6f0cf118..00000000 --- a/tests/fixtures/testswarm.key +++ /dev/null @@ -1,3 +0,0 @@ -/key/swarm/psk/1.0.0/ -/base16/ -278b9a199c43fa84178920bd9f5cbcd69e933ddf02a8f69e47a3ea5a1705512f \ No newline at end of file diff --git a/tests/fixtures/testswarm_linux.key b/tests/fixtures/testswarm_linux.key new file mode 100644 index 00000000..534e7acb --- /dev/null +++ b/tests/fixtures/testswarm_linux.key @@ -0,0 +1,3 @@ +/key/swarm/psk/1.0.0/ +/base16/ +278b9a199c43fa84178920bd9f5cbcd69e933ddf02a8f69e47a3ea5a1705513f \ No newline at end of file diff --git a/tests/fixtures/testswarm_mac.key b/tests/fixtures/testswarm_mac.key new file mode 100644 index 00000000..7490ebe9 --- /dev/null +++ b/tests/fixtures/testswarm_mac.key @@ -0,0 +1,3 @@ +/key/swarm/psk/1.0.0/ +/base16/ +e105d6caa191dc76ff553d36d094fafb2ad1c646000a52ebc89b488e17f61f92 \ No newline at end of file diff --git a/tests/fixtures/testswarm_windows.key b/tests/fixtures/testswarm_windows.key new file mode 100644 index 00000000..7490ebe9 --- /dev/null +++ b/tests/fixtures/testswarm_windows.key @@ -0,0 +1,3 @@ +/key/swarm/psk/1.0.0/ +/base16/ +e105d6caa191dc76ff553d36d094fafb2ad1c646000a52ebc89b488e17f61f92 \ No newline at end of file diff --git a/tests/run.py b/tests/run.py index f0d78c0e..67f3705f 100644 --- a/tests/run.py +++ b/tests/run.py @@ -105,12 +105,12 @@ def copy_fixtures_to_build_dir(build_directory): raise FileNotFoundError(f"Copy operation for didimage.png.file failed. Destination file not found: {image_file_dest}") # Copy testswarm.key - swarmkey_src = os.path.join(fixtures_directory, "testswarm.key") - swarmkey_dest = os.path.join(build_directory, "testswarm.key") + swarmkey_src = os.path.join(fixtures_directory, f"testswarm_{build_directory}.key") + swarmkey_dest = os.path.join(build_directory, f"testswarm.key") shutil.copyfile(swarmkey_src, swarmkey_dest) if not os.path.exists(swarmkey_dest): - raise FileNotFoundError(f"Copy operation for testswarm.key failed. Destination file not found: {swarmkey_dest}") + raise FileNotFoundError(f"Copy operation for testswarm_{build_directory}.key failed. Destination file not found: {swarmkey_dest}") print("\nimage.png and swarm key have been added to build directory successfully") From 9e9fce9070735bc83ef0dd868a0369ba1c8eaf80 Mon Sep 17 00:00:00 2001 From: Arnab Ghose Date: Mon, 20 May 2024 13:27:00 +0530 Subject: [PATCH 040/129] added timestamp for node log artifacts --- .github/workflows/tests.yml | 27 +++++++++++++++++++++------ 1 file changed, 21 insertions(+), 6 deletions(-) diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index cc2a882f..1eacb7ad 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -38,12 +38,16 @@ jobs: if: always() run: | cd tests && python3 -u pack_node_logs.py - + + - name: Set Timestamp for Node Logs + if: always() + run: echo "TIMESTAMP=$(date -u +'%Y-%m-%dT%H-%M-%SZ' | sed 's/:/-/g')" >> $GITHUB_ENV + - name: Uploading Quorum and Non-Quorum node logs as Artifacts if: always() uses: actions/upload-artifact@v4 with: - name: node-logs-linux + name: node-logs-linux-${{ env.TIMESTAMP }} path: tests/node_logs test-macos: @@ -80,12 +84,16 @@ jobs: if: always() run: | cd tests && python3 -u pack_node_logs.py - + + - name: Set Timestamp for Node Logs + if: always() + run: echo "TIMESTAMP=$(date -u +'%Y-%m-%dT%H-%M-%SZ' | sed 's/:/-/g')" >> $GITHUB_ENV + - name: Uploading Quorum and Non-Quorum node logs as Artifacts if: always() uses: actions/upload-artifact@v4 with: - name: node-logs-macos + name: node-logs-macos-${{ env.TIMESTAMP }} path: tests/node_logs test-windows: @@ -119,10 +127,17 @@ jobs: if: always() run: | cd tests && python3 -u pack_node_logs.py - + + - name: Set Timestamp for Node Logs + if: always() + shell: pwsh + run: | + $timestamp = Get-Date -Format "yyyy-MM-ddTHH-mm-ssZ" + echo "TIMESTAMP=$timestamp" >> $env:GITHUB_ENV + - name: Uploading Quorum and Non-Quorum node logs as Artifacts if: always() uses: actions/upload-artifact@v4 with: - name: node-logs-windows + name: node-logs-windows-${{ env.TIMESTAMP }} path: tests/node_logs From dc4e24e29e70dd53af2a609a33439dfdf6c3a327 Mon Sep 17 00:00:00 2001 From: Arnab Ghose Date: Mon, 20 May 2024 13:27:27 +0530 Subject: [PATCH 041/129] removed unneeded print statement --- tests/node/actions.py | 1 - 1 file changed, 1 deletion(-) diff --git a/tests/node/actions.py b/tests/node/actions.py index 72dcad05..629e253d 100644 --- a/tests/node/actions.py +++ b/tests/node/actions.py @@ -30,7 +30,6 @@ def quorum_config(node_config: dict, node_did_alias_map: dict, skip_adding_quoru else: for node, config in node_config.items(): did = get_did_by_alias(config, node_did_alias_map[node]) - print("got the didby alias: ", did) quorum_info = { "type": 2, "address": config["peerId"] + "." + did From b8e59a7a19fc2b4d848b4f8614efbf922f32f478 Mon Sep 17 00:00:00 2001 From: Maneesha-rubix Date: Thu, 23 May 2024 15:26:23 +0530 Subject: [PATCH 042/129] fix parse error in dump-token-chain --- block/block.go | 40 ++++++++++++++++++++++++++------------ core/quorum_initiator.go | 42 ++++++++++++++-------------------------- 2 files changed, 42 insertions(+), 40 deletions(-) diff --git a/block/block.go b/block/block.go index 83f89208..074e3bcd 100644 --- a/block/block.go +++ b/block/block.go @@ -58,17 +58,17 @@ const ( ) type TokenChainBlock struct { - TransactionType string `json:"transactionType"` - TokenOwner string `json:"owner"` - GenesisBlock *GenesisBlock `json:"genesisBlock"` - TransInfo *TransInfo `json:"transInfo"` - PledgeDetails []PledgeDetail `json:"pledgeDetails"` - QuorumSignature []string `json:"quorumSignature"` - SmartContract []byte `json:"smartContract"` - SmartContractData string `json:"smartContractData"` - TokenValue float64 `json:"tokenValue"` - ChildTokens []string `json:"childTokens"` - SenderSignature string `json:"senderSignature"` + TransactionType string `json:"transactionType"` + TokenOwner string `json:"owner"` + GenesisBlock *GenesisBlock `json:"genesisBlock"` + TransInfo *TransInfo `json:"transInfo"` + PledgeDetails []PledgeDetail `json:"pledgeDetails"` + QuorumSignature []CreditSignature `json:"quorumSignature"` + SmartContract []byte `json:"smartContract"` + SmartContractData string `json:"smartContractData"` + TokenValue float64 `json:"tokenValue"` + ChildTokens []string `json:"childTokens"` + SenderSignature *SenderSignature `json:"senderSignature"` } type PledgeDetail struct { @@ -85,6 +85,22 @@ type Block struct { log logger.Logger } +type CreditSignature struct { + Signature string `json:"signature"` + PrivSignature string `json:"priv_signature"` + DID string `json:"did"` + Hash string `json:"hash"` + SignType string `json:"sign_type"` //represents sign type (PkiSign == 0 or NlssSign==1) +} + +type SenderSignature struct { + NLSS_share string `json:"nlss_share_signature"` + Private_sign string `json:"priv_signature"` + DID string `json:"sender_did"` + Hash string `json:"hash"` + SignType int `json:"sign_type"` //represents sign type (PkiSign == 0 or NlssSign==1) +} + type BlockOption func(b *Block) func NoSignature() BlockOption { @@ -153,7 +169,7 @@ func CreateNewBlock(ctcb map[string]*Block, tcb *TokenChainBlock) *Block { if tcb.SmartContractData != "" { ntcb[TCSmartContractDataKey] = tcb.SmartContractData } - if tcb.SenderSignature != "" { + if tcb.SenderSignature != nil { ntcb[TCSenderSignatureKey] = tcb.SenderSignature } diff --git a/core/quorum_initiator.go b/core/quorum_initiator.go index 5ed16220..5d539207 100644 --- a/core/quorum_initiator.go +++ b/core/quorum_initiator.go @@ -1,7 +1,6 @@ package core import ( - "encoding/json" "errors" "fmt" "strconv" @@ -132,14 +131,6 @@ type CreditSignature struct { SignType string `json:"sign_type"` //represents sign type (PkiSign == 0 or NlssSign==1) } -type SenderSignature struct { - NLSS_share string `json:"nlss_share_signature"` - Private_sign string `json:"priv_signature"` - DID string `json:"sender_did"` - Hash string `json:"hash"` - SignType int `json:"sign_type"` //represents sign type (PkiSign == 0 or NlssSign==1) -} - type TokenArbitrationReq struct { Block []byte `json:"block"` } @@ -747,7 +738,7 @@ func (c *Core) finishConsensus(id string, qt int, p *ipfsport.Peer, status bool, var pledgingDID string if len(pledgingQuorumDID) > 0 { pledgingDID = pledgingQuorumDID[0] - } + } var signType string @@ -769,15 +760,15 @@ func (c *Core) finishConsensus(id string, qt int, p *ipfsport.Peer, status bool, PrivSignature: util.HexToStr(ps), DID: did, Hash: hash, - SignType: signType, + SignType: signType, } if cs.Result.SuccessCount < MinConsensusRequired-1 { - cs.P[did] = p + cs.P[did] = p cs.Credit.Credit = append(cs.Credit.Credit, csig) cs.Result.SuccessCount++ if did == pledgingDID { cs.Result.PledgingDIDSignStatus = true - } + } } else if (did == pledgingDID || cs.Result.PledgingDIDSignStatus) && cs.Result.SuccessCount == MinConsensusRequired-1 { cs.P[did] = p cs.Credit.Credit = append(cs.Credit.Credit, csig) @@ -937,14 +928,16 @@ func (c *Core) pledgeQuorumToken(cr *ConensusRequest, sc *contract.Contract, tid return nil, fmt.Errorf("invalid pledge request") } ti := sc.GetTransTokenInfo() - credit := make([]string, 0) + credit := make([]block.CreditSignature, 0) for _, csig := range cs.Credit.Credit { - jb, err := json.Marshal(csig) - if err != nil { - c.log.Error("Failed to parse quorum credit", "err", err) - return nil, fmt.Errorf("failed to parse quorum credit") + credit_ := block.CreditSignature{ + Signature: csig.Signature, + PrivSignature: csig.PrivSignature, + DID: csig.DID, + Hash: csig.Hash, + SignType: csig.SignType, } - credit = append(credit, string(jb)) + credit = append(credit, credit_) } ptds := make([]block.PledgeDetail, 0) for k, v := range pd.PledgedTokens { @@ -1020,20 +1013,13 @@ func (c *Core) pledgeQuorumToken(cr *ConensusRequest, sc *contract.Contract, tid return nil, fmt.Errorf("failed to fetch sender sign") } sender_sign_type := dc.GetSignType() - sender_sign_ := &SenderSignature{ + sender_sign := &block.SenderSignature{ NLSS_share: sender_share_sign, Private_sign: sender_priv_sign, DID: senderdid, Hash: sign_data, SignType: sender_sign_type, } - sender_sign, err := json.Marshal(sender_sign_) - if err != nil { - c.log.Error("failed to parse sender sign", "err", err) - return nil, fmt.Errorf("failed to parse sender sign") - } - - senderSignature := string(sender_sign) var tcb block.TokenChainBlock @@ -1093,7 +1079,7 @@ func (c *Core) pledgeQuorumToken(cr *ConensusRequest, sc *contract.Contract, tid QuorumSignature: credit, SmartContract: sc.GetBlock(), PledgeDetails: ptds, - SenderSignature: senderSignature, + SenderSignature: sender_sign, } } From 4b4643973944905f802028b237cf5c7c95bac8e4 Mon Sep 17 00:00:00 2001 From: Vaishnav CH Date: Fri, 24 May 2024 11:27:52 +0530 Subject: [PATCH 043/129] Add variables and equal distribution --- core/part_token.go | 2 +- core/quorum_initiator.go | 20 +++++++++++++------- 2 files changed, 14 insertions(+), 8 deletions(-) diff --git a/core/part_token.go b/core/part_token.go index 5e906911..40996688 100644 --- a/core/part_token.go +++ b/core/part_token.go @@ -24,7 +24,7 @@ func round(num float64) int { } func Ceilround(num float64) int { - return int(math.Floor(num)) + return int(math.Ceil(num)) } func floatPrecision(num float64, precision int) float64 { diff --git a/core/quorum_initiator.go b/core/quorum_initiator.go index 1416bf78..376e6ace 100644 --- a/core/quorum_initiator.go +++ b/core/quorum_initiator.go @@ -73,7 +73,7 @@ type ConsensusStatus struct { } type PledgeDetails struct { - //TransferAmount float64 + TransferAmount float64 RemPledgeTokens float64 NumPledgedTokens int PledgedTokens map[string][]string @@ -260,7 +260,7 @@ func (c *Core) initiateConsensus(cr *ConensusRequest, sc *contract.Contract, dc reqPledgeTokens = sc.GetTotalRBTs() } pd := PledgeDetails{ - //TransferAmount: reqPledgeTokens, + TransferAmount: reqPledgeTokens, RemPledgeTokens: floatPrecision(reqPledgeTokens, MaxDecimalPlaces), NumPledgedTokens: 0, PledgedTokens: make(map[string][]string), @@ -1071,13 +1071,17 @@ func (c *Core) initPledgeQuorumToken(cr *ConensusRequest, p *ipfsport.Peer, qt i return err } - //pledgeTokensPerQuorum := pd.TransferAmount / float64(MinQuorumRequired) + pledgeTokensPerQuorum := pd.TransferAmount / float64(MinQuorumRequired) + fmt.Println("Mininum quorum req is ", float64(MinQuorumRequired)) + fmt.Println("Transfer amount is ", pd.TransferAmount) + fmt.Println("Pledge token per quorum is ", pledgeTokensPerQuorum) // Request pledage token - if pd.RemPledgeTokens != 0 { + if pd.RemPledgeTokens > 0 { pr := PledgeRequest{ - TokensRequired: pd.RemPledgeTokens, + TokensRequired: CeilfloatPrecision(pledgeTokensPerQuorum, MaxDecimalPlaces), // Request the determined number of tokens per quorum, } + fmt.Println("Tokens required per quorum is ", pr.TokensRequired) // l := len(pd.PledgedTokens) // for i := pd.NumPledgedTokens; i < l; i++ { // pr.Tokens = append(pr.Tokens, cr.WholeTokens[i]) @@ -1098,7 +1102,9 @@ func (c *Core) initPledgeQuorumToken(cr *ConensusRequest, p *ipfsport.Peer, qt i if !c.checkIsPledged(ptcb) { pd.NumPledgedTokens++ pd.RemPledgeTokens = pd.RemPledgeTokens - prs.TokenValue[i] + fmt.Println("rem is ", pd.RemPledgeTokens) pd.RemPledgeTokens = floatPrecision(pd.RemPledgeTokens, 10) + fmt.Println("rem after float precision is ", pd.RemPledgeTokens) pd.PledgedTokenChainBlock[t] = prs.TokenChainBlock[i] pd.PledgedTokens[did] = append(pd.PledgedTokens[did], t) pd.TokenList = append(pd.TokenList, t) @@ -1122,8 +1128,8 @@ func (c *Core) initPledgeQuorumToken(cr *ConensusRequest, p *ipfsport.Peer, qt i err := fmt.Errorf("invalid pledge request") return err } - - if pd.RemPledgeTokens == 0 { + fmt.Println("Remaining pledge token after getting responce is ", pd.RemPledgeTokens) + if pd.RemPledgeTokens <= 0 { return nil } else if count == 300 { c.log.Error("Unable to pledge token") From dbfb55efa2dd8f47790b1fac0ecff6c81a297f91 Mon Sep 17 00:00:00 2001 From: Ashita Gupta Date: Mon, 27 May 2024 11:37:58 +0530 Subject: [PATCH 044/129] removed manual entering of DIDType --- command/addingpeerdetails.go | 16 ++++------------ 1 file changed, 4 insertions(+), 12 deletions(-) diff --git a/command/addingpeerdetails.go b/command/addingpeerdetails.go index 6c77d72d..9e911dde 100644 --- a/command/addingpeerdetails.go +++ b/command/addingpeerdetails.go @@ -10,7 +10,6 @@ import ( func (cmd *Command) AddPeerDetails() { var peerID string var did string - var did_type int var err error if cmd.peerID == "" { fmt.Print("Enter PeerID : ") @@ -19,11 +18,9 @@ func (cmd *Command) AddPeerDetails() { cmd.log.Error("Failed to get PeerID") return } - } else { peerID = cmd.peerID } - if !strings.HasPrefix(peerID, "12D3KooW") || len(peerID) < 52 { cmd.log.Error("Invalid PeerID") return @@ -44,21 +41,16 @@ func (cmd *Command) AddPeerDetails() { return } - fmt.Print("Enter DID Type : ") - _, err = fmt.Scan(&did_type) - if err != nil { - cmd.log.Error("Invalid DID Type") - return - } - if did_type < 0 || did_type > 4 { - cmd.log.Error("DID should be between 0 and 4") + // did_type = cmd.didType + if cmd.didType < 0 || cmd.didType > 4 { + cmd.log.Error("DID Type should be between 0 and 4") return } peer_detail := wallet.DIDPeerMap{ PeerID: peerID, DID: did, - DIDType: &did_type, + DIDType: &cmd.didType, } msg, status := cmd.c.AddPeer(&peer_detail) if !status { From aef69c2708cb6e075d72589ba9b929777424fbd8 Mon Sep 17 00:00:00 2001 From: Ashita Gupta Date: Mon, 27 May 2024 12:22:13 +0530 Subject: [PATCH 045/129] updating readme --- README.md | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/README.md b/README.md index f457f546..1c79bdbd 100644 --- a/README.md +++ b/README.md @@ -348,4 +348,23 @@ To get all explorer urls This following options are used for this command -port string Server/Host port (default "20000") +``` +To add the peer details manually +: To add the peer details by providing peerID, did and didType of the peer + +``` +./rubixgoplatform addpeerdetails -did bafybmiduo2rbar4hls7walzn4hhmtbmecqg72nvavz2bwspzc123451111 -peerID 12D3KooWQo7ExWLqTRD1qMUA1VyCGmrZ8covei9GBaGiKtDsxabc -port 20002 + +This following options are used for this command + -port string + Server/Host port (default "20000") + + -peerID string + Peerd ID + + -did string + DID address (default "") + + -didType int + DID type (0-Basic Mode, 1-Standard Mode, 2-Wallet Mode, 3-Child Mode, 4-Light Mode) (default 0) ``` \ No newline at end of file From c1c7c0af436ec9decb7f763d01b9c2e65fa2a377 Mon Sep 17 00:00:00 2001 From: Ashita Gupta Date: Mon, 27 May 2024 12:23:05 +0530 Subject: [PATCH 046/129] updating Readme --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 1c79bdbd..34ca4965 100644 --- a/README.md +++ b/README.md @@ -353,7 +353,7 @@ To add the peer details manually : To add the peer details by providing peerID, did and didType of the peer ``` -./rubixgoplatform addpeerdetails -did bafybmiduo2rbar4hls7walzn4hhmtbmecqg72nvavz2bwspzc123451111 -peerID 12D3KooWQo7ExWLqTRD1qMUA1VyCGmrZ8covei9GBaGiKtDsxabc -port 20002 +./rubixgoplatform addpeerdetails This following options are used for this command -port string From 81dbe086b00822c2f0d159945ae117a28362c9ae Mon Sep 17 00:00:00 2001 From: Maneesha-rubix Date: Tue, 28 May 2024 13:21:22 +0530 Subject: [PATCH 047/129] Fix DID mode compatibility issue --- client/did.go | 2 +- core/core.go | 12 ++++++++++++ 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/client/did.go b/client/did.go index ea51b372..89551a9f 100644 --- a/client/did.go +++ b/client/did.go @@ -48,7 +48,7 @@ func (c *Client) GetAllDIDs() (*model.GetAccountInfo, error) { } func (c *Client) CreateDID(cfg *did.DIDCreate) (string, bool) { - if cfg.Type < did.LiteDIDMode && cfg.Type > did.WalletDIDMode { + if cfg.Type < did.BasicDIDMode && cfg.Type > did.LiteDIDMode { return "Invalid DID mode", false } switch cfg.Type { diff --git a/core/core.go b/core/core.go index f608c287..e7116761 100644 --- a/core/core.go +++ b/core/core.go @@ -587,6 +587,12 @@ func (c *Core) SetupForienDIDQuorum(didStr string) (did.DIDCrypto, error) { return did.InitDIDQuorumc(didStr, c.didDir, ""), nil case did.LiteDIDMode: return did.InitDIDQuorum_Lt(didStr, c.didDir, ""), nil + case did.StandardDIDMode: + return did.InitDIDQuorumc(didStr, c.didDir, ""), nil + case did.WalletDIDMode: + return did.InitDIDQuorumc(didStr, c.didDir, ""), nil + case did.ChildDIDMode: + return did.InitDIDQuorumc(didStr, c.didDir, ""), nil default: return nil, fmt.Errorf("invalid did type") } @@ -631,6 +637,12 @@ func (c *Core) InitialiseDID(didStr string, didType int) (did.DIDCrypto, error) return did.InitDIDLite(didStr, c.didDir, nil), nil case did.BasicDIDMode: return did.InitDIDBasic(didStr, c.didDir, nil), nil + case did.StandardDIDMode: + return did.InitDIDStandard(didStr, c.didDir, nil), nil + case did.WalletDIDMode: + return did.InitDIDWallet(didStr, c.didDir, nil), nil + case did.ChildDIDMode: + return did.InitDIDChild(didStr, c.didDir, nil), nil default: return nil, fmt.Errorf("invalid did type, couldn't initialise") } From dc4c6cff18d5d60ace7c022f8d02a026fddb667a Mon Sep 17 00:00:00 2001 From: Maneesha-rubix Date: Tue, 28 May 2024 17:12:47 +0530 Subject: [PATCH 048/129] fix wallet and standard mode issues --- client/did.go | 8 ++++++++ command/did.go | 3 ++- core/core.go | 16 ++-------------- core/quorum_initiator.go | 15 ++++++++++++++- did/did.go | 6 ++++++ 5 files changed, 32 insertions(+), 16 deletions(-) diff --git a/client/did.go b/client/did.go index 89551a9f..b38eb581 100644 --- a/client/did.go +++ b/client/did.go @@ -186,6 +186,14 @@ func (c *Client) SetupDID(dc *did.DIDCreate) (string, bool) { !strings.Contains(dc.QuorumPrivKeyFile, did.QuorumPvtKeyFileName) { return "Required files are missing", false } + default: + if !strings.Contains(dc.PubImgFile, did.PubShareFileName) || + !strings.Contains(dc.DIDImgFileName, did.DIDImgFileName) || + !strings.Contains(dc.PubKeyFile, did.PubKeyFileName) || + !strings.Contains(dc.QuorumPubKeyFile, did.QuorumPubKeyFileName) || + !strings.Contains(dc.QuorumPrivKeyFile, did.QuorumPvtKeyFileName) { + return "Required files are missing", false + } } jd, err := json.Marshal(&dc) if err != nil { diff --git a/command/did.go b/command/did.go index d139543e..00cb9229 100644 --- a/command/did.go +++ b/command/did.go @@ -120,7 +120,8 @@ func (cmd *Command) CreateDID() { cmd.log.Error("failed to create image", "err", err) return } - } else if cmd.didType != did.BasicDIDMode { + } + if cmd.didType != did.BasicDIDMode && cmd.didType != did.LiteDIDMode { if cmd.privKeyFile == "" || cmd.pubKeyFile == "" { cmd.log.Error("private key & public key file names required") return diff --git a/core/core.go b/core/core.go index e7116761..56c414d8 100644 --- a/core/core.go +++ b/core/core.go @@ -587,14 +587,8 @@ func (c *Core) SetupForienDIDQuorum(didStr string) (did.DIDCrypto, error) { return did.InitDIDQuorumc(didStr, c.didDir, ""), nil case did.LiteDIDMode: return did.InitDIDQuorum_Lt(didStr, c.didDir, ""), nil - case did.StandardDIDMode: - return did.InitDIDQuorumc(didStr, c.didDir, ""), nil - case did.WalletDIDMode: - return did.InitDIDQuorumc(didStr, c.didDir, ""), nil - case did.ChildDIDMode: - return did.InitDIDQuorumc(didStr, c.didDir, ""), nil default: - return nil, fmt.Errorf("invalid did type") + return did.InitDIDQuorumc(didStr, c.didDir, ""), nil } } @@ -637,13 +631,7 @@ func (c *Core) InitialiseDID(didStr string, didType int) (did.DIDCrypto, error) return did.InitDIDLite(didStr, c.didDir, nil), nil case did.BasicDIDMode: return did.InitDIDBasic(didStr, c.didDir, nil), nil - case did.StandardDIDMode: - return did.InitDIDStandard(didStr, c.didDir, nil), nil - case did.WalletDIDMode: - return did.InitDIDWallet(didStr, c.didDir, nil), nil - case did.ChildDIDMode: - return did.InitDIDChild(didStr, c.didDir, nil), nil default: - return nil, fmt.Errorf("invalid did type, couldn't initialise") + return did.InitDIDBasic(didStr, c.didDir, nil), nil } } diff --git a/core/quorum_initiator.go b/core/quorum_initiator.go index 5d539207..ca6af25b 100644 --- a/core/quorum_initiator.go +++ b/core/quorum_initiator.go @@ -215,7 +215,20 @@ func (c *Core) SetupQuorum(didStr string, pwd string, pvtKeyPwd string) error { c.pqc[didStr] = dc } default: - return fmt.Errorf("DID Type is not supported") + dc := did.InitDIDQuorumc(didStr, c.didDir, pwd) + if dc == nil { + c.log.Error("Failed to setup quorum") + return fmt.Errorf("failed to setup quorum") + } + c.qc[didStr] = dc + if pvtKeyPwd != "" { + dc := did.InitDIDBasicWithPassword(didStr, c.didDir, pvtKeyPwd) + if dc == nil { + c.log.Error("Failed to setup quorum") + return fmt.Errorf("failed to setup quorum") + } + c.pqc[didStr] = dc + } } c.up.RunUnpledge() diff --git a/did/did.go b/did/did.go index 7edf5ba7..c123789e 100644 --- a/did/did.go +++ b/did/did.go @@ -260,6 +260,12 @@ func (d *DID) CreateDID(didCreate *DIDCreate) (string, error) { return "", err } + } else if didCreate.Type != LiteDIDMode { + _, err := util.Filecopy(didCreate.PubKeyFile, dirName+"/public/"+PubKeyFileName) + if err != nil { + d.log.Error("failed to copy pub key", "err", err) + return "", err + } } if didCreate.Type == ChildDIDMode { From 4429b250f55fc8c2db893ab3363b7f5a991ab98a Mon Sep 17 00:00:00 2001 From: Ashita Gupta Date: Wed, 29 May 2024 12:48:51 +0530 Subject: [PATCH 049/129] updating test files with addpeerdetails command and removed registerdid --- tests/node/actions.py | 5 ++++- tests/node/commands.py | 14 ++++++++++++++ tests/node/quorum.py | 11 +++++++++-- tests/scenarios/bip39_nlss_test.py | 21 ++++++++++++++++++--- tests/scenarios/rbt_transfer.py | 21 ++++++++++++++++++--- 5 files changed, 63 insertions(+), 9 deletions(-) diff --git a/tests/node/actions.py b/tests/node/actions.py index 629e253d..a1a05ed6 100644 --- a/tests/node/actions.py +++ b/tests/node/actions.py @@ -1,5 +1,5 @@ from .commands import cmd_run_rubix_servers, cmd_get_peer_id, cmd_create_did, cmd_register_did, \ - cmd_generate_rbt, cmd_add_quorum_dids, cmd_setup_quorum_dids, cmd_rbt_transfer, get_build_dir + cmd_generate_rbt, cmd_add_quorum_dids, cmd_setup_quorum_dids, cmd_rbt_transfer, get_build_dir, cmd_add_peer_details from .utils import get_node_name_from_idx, get_did_by_alias from config.utils import save_to_config_file, get_node_registry @@ -107,3 +107,6 @@ def rbt_transfer( sender_server_port: int, sender_grpc_port: int): cmd_rbt_transfer(sender_address, receiver_address, transfer_rbt, sender_server_port, sender_grpc_port) + +def add_peer_details(peer_id: str, did_id: str, did_type: int, server_port: int, grpc_port: int): + cmd_add_peer_details(peer_id, did_id, did_type, server_port, grpc_port) \ No newline at end of file diff --git a/tests/node/commands.py b/tests/node/commands.py index 999f316c..a44fd0d7 100644 --- a/tests/node/commands.py +++ b/tests/node/commands.py @@ -128,6 +128,20 @@ def cmd_register_did(did_id, server_port, grpc_port): os.chdir("../tests") return output +def cmd_add_peer_details(peer_id, did_id, did_type, server_port, grpc_port): + os.chdir("../" + get_build_dir()) + cmd_string = f"./rubixgoplatform addpeerdetails -peerID {peer_id} -did {did_id} -didType {did_type} -port {server_port} -grpcPort {grpc_port}" + if is_windows_os(): + cmd_string = f".\\rubixgoplatform addpeerdetails -peerID {peer_id} -did {did_id} -didType {did_type} -port {server_port} -grpcPort {grpc_port}" + output, code = run_command(cmd_string, True) + print(output) + + if code != 0: + raise Exception("Error occurred while run the command: " + cmd_string) + + os.chdir("../tests") + return output + def cmd_generate_rbt(did_id, numTokens, server_port, grpc_port): os.chdir("../" + get_build_dir()) cmd_string = f"./rubixgoplatform generatetestrbt -did {did_id} -numTokens {numTokens} -port {server_port} -grpcPort {grpc_port}" diff --git a/tests/node/quorum.py b/tests/node/quorum.py index cb65ccbd..51e8792c 100644 --- a/tests/node/quorum.py +++ b/tests/node/quorum.py @@ -2,7 +2,7 @@ import time from .actions import setup_rubix_nodes, create_and_register_did, \ - fund_did_with_rbt, quorum_config + fund_did_with_rbt, quorum_config,add_peer_details from config.utils import save_to_config_file, load_from_config_file QUORUM_CONFIG_PATH = "./quorum_config.json" @@ -19,12 +19,19 @@ def run_quorum_nodes(only_run_nodes, skip_adding_quorums): print("Creating, Registering and Funding Quorum DIDs\n") for node, config in node_config.items(): - did = create_and_register_did(config, did_alias) + did = create_and_register_did(config, did_alias, register_did=False) fund_did_with_rbt(config, did) # Selecting DIDs for quorum setup node_did_alias_map[node] = did_alias + + #Temporary adding details manually + for _, val1 in node_config.items(): + for _, val2 in node_config.items(): + add_peer_details(val1["peerId"], val1["dids"]["did_quorum"], 4, val2["server"], val2["grpcPort"]) + + save_to_config_file(QUORUM_CONFIG_PATH, node_config) print("\nquorum_config.json is created") diff --git a/tests/scenarios/bip39_nlss_test.py b/tests/scenarios/bip39_nlss_test.py index 74aa300c..cf4fc471 100644 --- a/tests/scenarios/bip39_nlss_test.py +++ b/tests/scenarios/bip39_nlss_test.py @@ -1,5 +1,5 @@ from node.actions import rbt_transfer, fund_did_with_rbt, setup_rubix_nodes, \ - create_and_register_did, add_quorums + create_and_register_did, add_quorums, add_peer_details from node.utils import get_did_by_alias from config.utils import save_to_config_file, load_from_config_file from helper.utils import expect_failure, expect_success @@ -15,10 +15,10 @@ def setup(): config_bip39 = node_config["node11"] config_nlss = node_config["node12"] - create_and_register_did(config_bip39, "bip39_1", did_type=4) + create_and_register_did(config_bip39, "bip39_1", did_type=4, register_did=False) - create_and_register_did(config_nlss, "nlss_1", did_type=0) + create_and_register_did(config_nlss, "nlss_1", did_type=0, register_did=False) save_to_config_file(__node_config_path, node_config) @@ -53,7 +53,21 @@ def nlss_to_bip39(node_config): expect_success(fund_did_with_rbt)(node_nlss, did_nlss, 3) print("Funded NLSS DID with 3 RBT") + #adding peer details of bip39 node and nlss node to quorums + add_peer_details(node_bip39["peerId"], did_bip39, 4, 20004, 10504) + add_peer_details(node_bip39["peerId"], did_bip39, 4, 20005, 10505) + add_peer_details(node_bip39["peerId"], did_bip39, 4, 20006, 10506) + add_peer_details(node_bip39["peerId"], did_bip39, 4, 20007, 10507) + add_peer_details(node_bip39["peerId"], did_bip39, 4, 20008, 10508) + + add_peer_details(node_nlss["peerId"], did_nlss, 0, 20004, 10504) + add_peer_details(node_nlss["peerId"], did_nlss, 0, 20005, 10505) + add_peer_details(node_nlss["peerId"], did_nlss, 0, 20006, 10506) + add_peer_details(node_nlss["peerId"], did_nlss, 0, 20007, 10507) + add_peer_details(node_nlss["peerId"], did_nlss, 0, 20008, 10508) + print("\n2. Transferring 1 RBT from NLSS DID to BIP39 DID....") + add_peer_details(node_bip39["peerId"], did_bip39, 4, server_port_nlss, grpc_port_nlss) #adding peer details of bip39 node to nlss expect_success(rbt_transfer)(address_nlss, address_bip39, 1, server_port_nlss, grpc_port_nlss) print("Transferred 1 RBT from NLSS DID to BIP39 DID") @@ -76,6 +90,7 @@ def bip39_to_nlss(node_config): print("------ Test Case (PASS): Transferring whole, part and mix RBT from BIP39 DID to NLSS DID ------\n") print("\n4. Transferring 0.5 RBT from BIP39 DID to NLSS DID....") + add_peer_details(node_nlss["peerId"], did_nlss, 0, server_port_bip39, grpc_port_bip39) #adding peer details of nlss node to bip39 expect_success(rbt_transfer)(address_bip39, address_nlss, 0.5, server_port_bip39, grpc_port_bip39) print("Transferred 0.5 RBT from BIP39 DID to NLSS DID") diff --git a/tests/scenarios/rbt_transfer.py b/tests/scenarios/rbt_transfer.py index 7f5c2da0..8fa56ed4 100644 --- a/tests/scenarios/rbt_transfer.py +++ b/tests/scenarios/rbt_transfer.py @@ -1,5 +1,5 @@ from node.actions import rbt_transfer, fund_did_with_rbt, setup_rubix_nodes, \ - create_and_register_did, add_quorums + create_and_register_did, add_quorums, add_peer_details from node.utils import get_did_by_alias from config.utils import save_to_config_file, load_from_config_file from helper.utils import expect_failure, expect_success @@ -15,8 +15,8 @@ def setup(): config_A = node_config["node9"] config_B = node_config["node10"] - create_and_register_did(config_A, "did_a") - create_and_register_did(config_B, "did_b") + create_and_register_did(config_A, "did_a", register_did=False) + create_and_register_did(config_B, "did_b", register_did=False) save_to_config_file(__node_config_path, node_config) @@ -88,11 +88,25 @@ def shuttle_transfer(config): print("------ Test Case (PASS): Shuttle transfer started ------\n") + #adding peer details of node A and node B to quorums + add_peer_details(node_A_info["peerId"], did_A, 4, 20004, 10504) + add_peer_details(node_A_info["peerId"], did_A, 4, 20005, 10505) + add_peer_details(node_A_info["peerId"], did_A, 4, 20006, 10506) + add_peer_details(node_A_info["peerId"], did_A, 4, 20007, 10507) + add_peer_details(node_A_info["peerId"], did_A, 4, 20008, 10508) + + add_peer_details(node_B_info["peerId"], did_B, 4, 20004, 10504) + add_peer_details(node_B_info["peerId"], did_B, 4, 20005, 10505) + add_peer_details(node_B_info["peerId"], did_B, 4, 20006, 10506) + add_peer_details(node_B_info["peerId"], did_B, 4, 20007, 10507) + add_peer_details(node_B_info["peerId"], did_B, 4, 20008, 10508) + print("\n1. Generating 2 whole RBT for A") expect_success(fund_did_with_rbt)(node_A_info, did_A, 2) print("Funded node A with 2 RBT") print("\n2. Transferring 0.5 RBT from A to B....") + add_peer_details(node_B_info["peerId"], did_B, 4, server_port_A, grpc_port_A) #adding peer details of node B to node A expect_success(rbt_transfer)(address_A, address_B, 0.5, server_port_A, grpc_port_A) print("Transferred 0.5 RBT from A to B") @@ -101,6 +115,7 @@ def shuttle_transfer(config): print("Transferred 1.499 RBT from A to B") print("\n4. Transferring 0.25 RBT from B to A....") + add_peer_details(node_A_info["peerId"], did_A, 4, server_port_B, grpc_port_B) #adding peer details of node A to node B expect_success(rbt_transfer)(address_B, address_A, 0.25, server_port_B, grpc_port_B) print("Transferred 0.25 RBT from B to A") From ef6759dce71630194fc9f56f440a18e992de0206 Mon Sep 17 00:00:00 2001 From: Ashita Gupta Date: Wed, 29 May 2024 16:43:13 +0530 Subject: [PATCH 050/129] updating test files to add peer details --- tests/scenarios/bip39_nlss_test.py | 11 +++++++++++ tests/scenarios/rbt_transfer.py | 7 +++++++ 2 files changed, 18 insertions(+) diff --git a/tests/scenarios/bip39_nlss_test.py b/tests/scenarios/bip39_nlss_test.py index cf4fc471..ea6aea2a 100644 --- a/tests/scenarios/bip39_nlss_test.py +++ b/tests/scenarios/bip39_nlss_test.py @@ -3,6 +3,7 @@ from node.utils import get_did_by_alias from config.utils import save_to_config_file, load_from_config_file from helper.utils import expect_failure, expect_success +from node.quorum import get_quorum_config __node_config_path = "./bip39_nlss_config.json" @@ -66,6 +67,11 @@ def nlss_to_bip39(node_config): add_peer_details(node_nlss["peerId"], did_nlss, 0, 20007, 10507) add_peer_details(node_nlss["peerId"], did_nlss, 0, 20008, 10508) + quorum_config = get_quorum_config() + + for _, val in quorum_config.items(): + add_peer_details(val["peerId"], val["dids"]["did_quorum"], 4, server_port_nlss, grpc_port_nlss) + print("\n2. Transferring 1 RBT from NLSS DID to BIP39 DID....") add_peer_details(node_bip39["peerId"], did_bip39, 4, server_port_nlss, grpc_port_nlss) #adding peer details of bip39 node to nlss expect_success(rbt_transfer)(address_nlss, address_bip39, 1, server_port_nlss, grpc_port_nlss) @@ -86,6 +92,11 @@ def bip39_to_nlss(node_config): server_port_bip39, grpc_port_bip39 = node_bip39["server"], node_bip39["grpcPort"] did_bip39, did_nlss = get_did_by_alias(node_bip39, "bip39_1"), get_did_by_alias(node_nlss, "nlss_1") address_bip39, address_nlss = node_bip39["peerId"]+"."+did_bip39, node_nlss["peerId"]+"."+did_nlss + + quorum_config = get_quorum_config() + + for _, val in quorum_config.items(): + add_peer_details(val["peerId"], val["dids"]["did_quorum"], 4, server_port_bip39, grpc_port_bip39) print("------ Test Case (PASS): Transferring whole, part and mix RBT from BIP39 DID to NLSS DID ------\n") diff --git a/tests/scenarios/rbt_transfer.py b/tests/scenarios/rbt_transfer.py index 8fa56ed4..89a95a6a 100644 --- a/tests/scenarios/rbt_transfer.py +++ b/tests/scenarios/rbt_transfer.py @@ -3,6 +3,7 @@ from node.utils import get_did_by_alias from config.utils import save_to_config_file, load_from_config_file from helper.utils import expect_failure, expect_success +from node.quorum import get_quorum_config __node_config_path = "./rbt_transfer_config.json" @@ -101,6 +102,12 @@ def shuttle_transfer(config): add_peer_details(node_B_info["peerId"], did_B, 4, 20007, 10507) add_peer_details(node_B_info["peerId"], did_B, 4, 20008, 10508) + quorum_config = get_quorum_config() + + for _, val in quorum_config.items(): + add_peer_details(val["peerId"], val["dids"]["did_quorum"], 4, server_port_A, grpc_port_A) + add_peer_details(val["peerId"], val["dids"]["did_quorum"], 4, server_port_B, grpc_port_B) + print("\n1. Generating 2 whole RBT for A") expect_success(fund_did_with_rbt)(node_A_info, did_A, 2) print("Funded node A with 2 RBT") From 8587afc25ab386bed8990909fbf8e29c7829b885 Mon Sep 17 00:00:00 2001 From: harirubix Date: Wed, 29 May 2024 17:49:45 +0530 Subject: [PATCH 051/129] read peerid from db and added tests --- core/quorum.go | 29 ++++++++++++++++++++++++++++- core/transfer.go | 22 ++++++---------------- tests/node/actions.py | 2 +- tests/scenarios/bip39_nlss_test.py | 14 ++++++-------- tests/scenarios/rbt_transfer.py | 27 ++++++++++++--------------- 5 files changed, 53 insertions(+), 41 deletions(-) diff --git a/core/quorum.go b/core/quorum.go index c2b502b0..e7489762 100644 --- a/core/quorum.go +++ b/core/quorum.go @@ -21,6 +21,13 @@ const ( TokenChainNotSynced ) +type QuorumDIDPeerMap struct { + DID string `gorm:"column:did;primaryKey"` + DIDType *int `gorm:"column:did_type"` + PeerID string `gorm:"column:peer_id"` + DIDLastChar string `gorm:"column:did_last_char"` +} + type QuorumManager struct { ql []string s storage.Storage @@ -86,7 +93,18 @@ func (qm *QuorumManager) GetQuorum(t int, lastChar string) []string { } return quorumAddrList case QuorumTypeTwo: - return qm.ql + var quorumAddrList []string + quorumCount := 0 + for _, q := range qm.ql { + peerID := qm.GetPeerID(q) + addr := string(peerID + "." + q) + quorumAddrList = append(quorumAddrList, addr) + quorumCount = quorumCount + 1 + if quorumCount == 7 { + break + } + } + return quorumAddrList } return nil } @@ -112,3 +130,12 @@ func (qm *QuorumManager) RemoveAllQuorum(t int) error { } return err } + +func (qm *QuorumManager) GetPeerID(did string) string { + var dm QuorumDIDPeerMap + err := qm.s.Read(wallet.DIDPeerStorage, &dm, "did=?", did) + if err != nil { + return "" + } + return dm.PeerID +} diff --git a/core/transfer.go b/core/transfer.go index d4b2f516..4c808a61 100644 --- a/core/transfer.go +++ b/core/transfer.go @@ -9,7 +9,6 @@ import ( "github.com/rubixchain/rubixgoplatform/contract" "github.com/rubixchain/rubixgoplatform/core/model" "github.com/rubixchain/rubixgoplatform/core/wallet" - "github.com/rubixchain/rubixgoplatform/util" "github.com/rubixchain/rubixgoplatform/wrapper/uuid" ) @@ -33,21 +32,12 @@ func (c *Core) initiateRBTTransfer(reqID string, req *model.RBTTransferRequest) resp.Message = "Sender and receiver cannot be same" return resp } - - if !strings.Contains(req.Sender, ".") || !strings.Contains(req.Receiver, ".") { - resp.Message = "Sender and receiver address should be of the format PeerID.DID" - return resp - } - - _, did, ok := util.ParseAddress(req.Sender) - if !ok { - resp.Message = "Invalid sender DID" - return resp - } - - rpeerid, rdid, ok := util.ParseAddress(req.Receiver) - if !ok { - resp.Message = "Invalid receiver DID" + did := req.Sender + rdid := req.Receiver + rpeerid := c.w.GetPeerID(rdid) + if rpeerid == "" { + c.log.Error("Peer ID not found", "did", rdid) + resp.Message = "invalid address, Peer ID not found" return resp } diff --git a/tests/node/actions.py b/tests/node/actions.py index a1a05ed6..dd8854f3 100644 --- a/tests/node/actions.py +++ b/tests/node/actions.py @@ -32,7 +32,7 @@ def quorum_config(node_config: dict, node_did_alias_map: dict, skip_adding_quoru did = get_did_by_alias(config, node_did_alias_map[node]) quorum_info = { "type": 2, - "address": config["peerId"] + "." + did + "address": did } quorum_list.append(quorum_info) diff --git a/tests/scenarios/bip39_nlss_test.py b/tests/scenarios/bip39_nlss_test.py index ea6aea2a..50c3e0d2 100644 --- a/tests/scenarios/bip39_nlss_test.py +++ b/tests/scenarios/bip39_nlss_test.py @@ -46,7 +46,6 @@ def nlss_to_bip39(node_config): node_bip39, node_nlss = node_config["node11"], node_config["node12"] server_port_nlss, grpc_port_nlss = node_nlss["server"], node_nlss["grpcPort"] did_bip39, did_nlss = get_did_by_alias(node_bip39, "bip39_1"), get_did_by_alias(node_nlss, "nlss_1") - address_bip39, address_nlss = node_bip39["peerId"]+"."+did_bip39, node_nlss["peerId"]+"."+did_nlss print("------ Test Case (PASS): Transferring whole, part and mix RBT from NLSS DID to BIP39 DID ------\n") @@ -74,15 +73,15 @@ def nlss_to_bip39(node_config): print("\n2. Transferring 1 RBT from NLSS DID to BIP39 DID....") add_peer_details(node_bip39["peerId"], did_bip39, 4, server_port_nlss, grpc_port_nlss) #adding peer details of bip39 node to nlss - expect_success(rbt_transfer)(address_nlss, address_bip39, 1, server_port_nlss, grpc_port_nlss) + expect_success(rbt_transfer)(did_nlss, did_bip39, 1, server_port_nlss, grpc_port_nlss) print("Transferred 1 RBT from NLSS DID to BIP39 DID") print("\n3. Transferring 1.5 RBT from NLSS DID to BIP39 DID....") - expect_success(rbt_transfer)(address_nlss, address_bip39, 1.5, server_port_nlss, grpc_port_nlss) + expect_success(rbt_transfer)(did_nlss, did_bip39, 1.5, server_port_nlss, grpc_port_nlss) print("Transferred 1.5 RBT from NLSS DID to BIP39 DID") print("\n4. Transferring 0.5 RBT from NLSS DID to BIP39 DID....") - expect_success(rbt_transfer)(address_nlss, address_bip39, 0.5, server_port_nlss, grpc_port_nlss) + expect_success(rbt_transfer)(did_nlss, did_bip39, 0.5, server_port_nlss, grpc_port_nlss) print("Transferred 0.5 RBT from NLSS DID to BIP39 DID") print("\n------ Test Case (PASS): Transferring whole, part and mix RBT from NLSS DID to BIP39 DID completed ------\n") @@ -91,7 +90,6 @@ def bip39_to_nlss(node_config): node_bip39, node_nlss = node_config["node11"], node_config["node12"] server_port_bip39, grpc_port_bip39 = node_bip39["server"], node_bip39["grpcPort"] did_bip39, did_nlss = get_did_by_alias(node_bip39, "bip39_1"), get_did_by_alias(node_nlss, "nlss_1") - address_bip39, address_nlss = node_bip39["peerId"]+"."+did_bip39, node_nlss["peerId"]+"."+did_nlss quorum_config = get_quorum_config() @@ -102,14 +100,14 @@ def bip39_to_nlss(node_config): print("\n4. Transferring 0.5 RBT from BIP39 DID to NLSS DID....") add_peer_details(node_nlss["peerId"], did_nlss, 0, server_port_bip39, grpc_port_bip39) #adding peer details of nlss node to bip39 - expect_success(rbt_transfer)(address_bip39, address_nlss, 0.5, server_port_bip39, grpc_port_bip39) + expect_success(rbt_transfer)(did_bip39, did_nlss, 0.5, server_port_bip39, grpc_port_bip39) print("Transferred 0.5 RBT from BIP39 DID to NLSS DID") print("\n3. Transferring 1.5 RBT from BIP39 DID to NLSS DID....") - expect_success(rbt_transfer)(address_bip39, address_nlss, 1.5, server_port_bip39, grpc_port_bip39) + expect_success(rbt_transfer)(did_bip39, did_nlss, 1.5, server_port_bip39, grpc_port_bip39) print("Transferred 1.5 RBT from BIP39 DID to NLSS DID") print("\n2. Transferring 1 RBT from BIP39 DID to NLSS DID....") - expect_success(rbt_transfer)(address_bip39, address_nlss, 1, server_port_bip39, grpc_port_bip39) + expect_success(rbt_transfer)(did_bip39, did_nlss, 1, server_port_bip39, grpc_port_bip39) print("Transferred 1 RBT from BIP39 DID to NLSS DID") diff --git a/tests/scenarios/rbt_transfer.py b/tests/scenarios/rbt_transfer.py index 89a95a6a..b47b1208 100644 --- a/tests/scenarios/rbt_transfer.py +++ b/tests/scenarios/rbt_transfer.py @@ -50,12 +50,11 @@ def max_decimal_place_transfer(config): node_A_info, node_B_info = config["node9"], config["node10"] server_port_B, grpc_port_B = node_B_info["server"], node_B_info["grpcPort"] did_A, did_B = get_did_by_alias(node_A_info, "did_a"), get_did_by_alias(node_B_info, "did_b") - address_A, address_B = node_A_info["peerId"]+"."+did_A, node_B_info["peerId"]+"."+did_B print("------ Test Case (FAIL) : Transferring 0.00000009 RBT from B which is more than allowed decimal places ------") print("\nTransferring 0.00000009 RBT from B to A....") - expect_failure(rbt_transfer)(address_B, address_A, 0.00000009, server_port_B, grpc_port_B) + expect_failure(rbt_transfer)(did_B, did_A, 0.00000009, server_port_B, grpc_port_B) print("\n------ Test Case (FAIL) : Transferring 0.00000009 RBT from B which is more than allowed decimal places completed ------\n") @@ -64,19 +63,18 @@ def insufficient_balance_transfer(config): server_port_A, grpc_port_A = node_A_info["server"], node_A_info["grpcPort"] server_port_B, grpc_port_B = node_B_info["server"], node_B_info["grpcPort"] did_A, did_B = get_did_by_alias(node_A_info, "did_a"), get_did_by_alias(node_B_info, "did_b") - address_A, address_B = node_A_info["peerId"]+"."+did_A, node_B_info["peerId"]+"."+did_B print("\n------ Test Case (FAIL) : Transferring 100 RBT from A which has zero balance ------") print("\nTransferring 100 RBT from A to B....") - expect_failure(rbt_transfer)(address_A, address_B, 100, server_port_A, grpc_port_A) + expect_failure(rbt_transfer)(did_A, did_B, 100, server_port_A, grpc_port_A) print("\n------ Test Case (FAIL) : Transferring 100 RBT from A which has zero balance completed ------\n") print("\n------ Test Case (FAIL) : Transferring 100 RBT from B which has insufficient balance ------") print("\nTransferring 100 RBT from B to A....") - expect_failure(rbt_transfer)(address_B, address_A, 0.25, server_port_B, grpc_port_B) + expect_failure(rbt_transfer)(did_B, did_A, 0.25, server_port_B, grpc_port_B) print("\n------ Test Case (FAIL) : Transferring 100 RBT from B which has insufficient balance completed ------\n") @@ -85,7 +83,6 @@ def shuttle_transfer(config): server_port_A, grpc_port_A = node_A_info["server"], node_A_info["grpcPort"] server_port_B, grpc_port_B = node_B_info["server"], node_B_info["grpcPort"] did_A, did_B = get_did_by_alias(node_A_info, "did_a"), get_did_by_alias(node_B_info, "did_b") - address_A, address_B = node_A_info["peerId"]+"."+did_A, node_B_info["peerId"]+"."+did_B print("------ Test Case (PASS): Shuttle transfer started ------\n") @@ -114,32 +111,32 @@ def shuttle_transfer(config): print("\n2. Transferring 0.5 RBT from A to B....") add_peer_details(node_B_info["peerId"], did_B, 4, server_port_A, grpc_port_A) #adding peer details of node B to node A - expect_success(rbt_transfer)(address_A, address_B, 0.5, server_port_A, grpc_port_A) + expect_success(rbt_transfer)(did_A, did_B, 0.5, server_port_A, grpc_port_A) print("Transferred 0.5 RBT from A to B") print("\n3. Transferring 1.499 RBT from A to B....") - expect_success(rbt_transfer)(address_A, address_B, 1.499, server_port_A, grpc_port_A) + expect_success(rbt_transfer)(did_A, did_B, 1.499, server_port_A, grpc_port_A) print("Transferred 1.499 RBT from A to B") print("\n4. Transferring 0.25 RBT from B to A....") add_peer_details(node_A_info["peerId"], did_A, 4, server_port_B, grpc_port_B) #adding peer details of node A to node B - expect_success(rbt_transfer)(address_B, address_A, 0.25, server_port_B, grpc_port_B) + expect_success(rbt_transfer)(did_B, did_A, 0.25, server_port_B, grpc_port_B) print("Transferred 0.25 RBT from B to A") print("\n5. Transferring 0.25 RBT from B to A....") - expect_success(rbt_transfer)(address_B, address_A, 0.25, server_port_B, grpc_port_B) + expect_success(rbt_transfer)(did_B, did_A, 0.25, server_port_B, grpc_port_B) print("Transferred 0.25 RBT from B to A") print("\n6. Transferring 0.25 RBT from B to A....") - expect_success(rbt_transfer)(address_B, address_A, 0.25, server_port_B, grpc_port_B) + expect_success(rbt_transfer)(did_B, did_A, 0.25, server_port_B, grpc_port_B) print("Transferred 0.25 RBT from B to A") print("\n7. Transferring 0.25 RBT from B to A....") - expect_success(rbt_transfer)(address_B, address_A, 0.25, server_port_B, grpc_port_B) + expect_success(rbt_transfer)(did_B, did_A, 0.25, server_port_B, grpc_port_B) print("Transferred 0.25 RBT from B to A") print("\n8. Transferring 1 RBT from A to B....") - expect_success(rbt_transfer)(address_A, address_B, 1, server_port_A, grpc_port_A) + expect_success(rbt_transfer)(did_A, did_B, 1, server_port_A, grpc_port_A) print("Transferred 1 RBT from A to B") print("\n9. Generating 2 whole RBT for A") @@ -147,11 +144,11 @@ def shuttle_transfer(config): print("Funded node A with 2 RBT") print("\n10. Transferring 2 RBT from A to B....") - expect_success(rbt_transfer)(address_A, address_B, 2, server_port_A, grpc_port_A) + expect_success(rbt_transfer)(did_A, did_B, 2, server_port_A, grpc_port_A) print("Transferred 2 RBT from A to B") print("\n11. Transferring 0.001 RBT from A to B....") - expect_success(rbt_transfer)(address_A, address_B, 0.001, server_port_A, grpc_port_A) + expect_success(rbt_transfer)(did_A, did_B, 0.001, server_port_A, grpc_port_A) print("Transferred 0.001 RBT from A to B") print("\n------ Test Case (PASS): Shuttle transfer completed ------\n") From 55aa96528516ec5993099421d7671c0c7149aba6 Mon Sep 17 00:00:00 2001 From: Vaishnav CH Date: Fri, 31 May 2024 16:46:02 +0530 Subject: [PATCH 052/129] Add minimum pledge amount fix --- core/quorum_initiator.go | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/core/quorum_initiator.go b/core/quorum_initiator.go index 75c16766..9076aaec 100644 --- a/core/quorum_initiator.go +++ b/core/quorum_initiator.go @@ -312,6 +312,10 @@ func (c *Core) initiateConsensus(cr *ConensusRequest, sc *contract.Contract, dc case SmartContractExecuteMode: reqPledgeTokens = sc.GetTotalRBTs() } + //Minimum pledge value is 0.005 (ie, 0.005/5 = 0.001 per each quorum) + if reqPledgeTokens < 0.00005 { + reqPledgeTokens = 0.00005 + } pd := PledgeDetails{ TransferAmount: reqPledgeTokens, RemPledgeTokens: floatPrecision(reqPledgeTokens, MaxDecimalPlaces), @@ -1215,7 +1219,7 @@ func (c *Core) initPledgeQuorumToken(cr *ConensusRequest, p *ipfsport.Peer, qt i pd.NumPledgedTokens++ pd.RemPledgeTokens = pd.RemPledgeTokens - prs.TokenValue[i] fmt.Println("rem is ", pd.RemPledgeTokens) - pd.RemPledgeTokens = floatPrecision(pd.RemPledgeTokens, 10) + pd.RemPledgeTokens = floatPrecision(pd.RemPledgeTokens, MaxDecimalPlaces) fmt.Println("rem after float precision is ", pd.RemPledgeTokens) pd.PledgedTokenChainBlock[t] = prs.TokenChainBlock[i] pd.PledgedTokens[did] = append(pd.PledgedTokens[did], t) From 4af4610121a45c3657d76f41621976d29a955454 Mon Sep 17 00:00:00 2001 From: Vaishnav CH Date: Fri, 31 May 2024 16:46:28 +0530 Subject: [PATCH 053/129] Add missing `MaxDecimalPlaces` --- core/part_token.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/core/part_token.go b/core/part_token.go index 40996688..a90ec2e2 100644 --- a/core/part_token.go +++ b/core/part_token.go @@ -99,7 +99,7 @@ func (c *Core) GetTokens(dc did.DIDCrypto, did string, value float64) ([]wallet. for i := range pt { if pt[i].TokenValue <= rem { wt = append(wt, pt[i]) - rem = floatPrecision(rem-pt[i].TokenValue, 10) + rem = floatPrecision(rem-pt[i].TokenValue, MaxDecimalPlaces) idx = append(idx, i) } else { rpt = append(rpt, pt[i]) @@ -111,7 +111,7 @@ func (c *Core) GetTokens(dc did.DIDCrypto, did string, value float64) ([]wallet. return wt, nil } if len(rpt) > 0 { - parts := []float64{rem, floatPrecision(rpt[0].TokenValue-rem, 10)} + parts := []float64{rem, floatPrecision(rpt[0].TokenValue-rem, MaxDecimalPlaces)} c.w.ReleaseToken(rpt[0].TokenID) npt, err := c.createPartToken(dc, did, rpt[0].TokenID, parts, 2) if err != nil { From 535fbd1c6df02e6690cedab3b4b4f8d066f45678 Mon Sep 17 00:00:00 2001 From: Vaishnav CH Date: Wed, 5 Jun 2024 12:36:33 +0530 Subject: [PATCH 054/129] Remove loggers used for testing --- core/quorum_initiator.go | 8 -------- 1 file changed, 8 deletions(-) diff --git a/core/quorum_initiator.go b/core/quorum_initiator.go index 9076aaec..7c0f1b19 100644 --- a/core/quorum_initiator.go +++ b/core/quorum_initiator.go @@ -1188,16 +1188,11 @@ func (c *Core) initPledgeQuorumToken(cr *ConensusRequest, p *ipfsport.Peer, qt i } pledgeTokensPerQuorum := pd.TransferAmount / float64(MinQuorumRequired) - fmt.Println("Mininum quorum req is ", float64(MinQuorumRequired)) - fmt.Println("Transfer amount is ", pd.TransferAmount) - fmt.Println("Pledge token per quorum is ", pledgeTokensPerQuorum) - // Request pledage token if pd.RemPledgeTokens > 0 { pr := PledgeRequest{ TokensRequired: CeilfloatPrecision(pledgeTokensPerQuorum, MaxDecimalPlaces), // Request the determined number of tokens per quorum, } - fmt.Println("Tokens required per quorum is ", pr.TokensRequired) // l := len(pd.PledgedTokens) // for i := pd.NumPledgedTokens; i < l; i++ { // pr.Tokens = append(pr.Tokens, cr.WholeTokens[i]) @@ -1218,9 +1213,7 @@ func (c *Core) initPledgeQuorumToken(cr *ConensusRequest, p *ipfsport.Peer, qt i if !c.checkIsPledged(ptcb) { pd.NumPledgedTokens++ pd.RemPledgeTokens = pd.RemPledgeTokens - prs.TokenValue[i] - fmt.Println("rem is ", pd.RemPledgeTokens) pd.RemPledgeTokens = floatPrecision(pd.RemPledgeTokens, MaxDecimalPlaces) - fmt.Println("rem after float precision is ", pd.RemPledgeTokens) pd.PledgedTokenChainBlock[t] = prs.TokenChainBlock[i] pd.PledgedTokens[did] = append(pd.PledgedTokens[did], t) pd.TokenList = append(pd.TokenList, t) @@ -1244,7 +1237,6 @@ func (c *Core) initPledgeQuorumToken(cr *ConensusRequest, p *ipfsport.Peer, qt i err := fmt.Errorf("invalid pledge request") return err } - fmt.Println("Remaining pledge token after getting responce is ", pd.RemPledgeTokens) if pd.RemPledgeTokens <= 0 { return nil } else if count == 300 { From 1c555b14286d01f853d96dc1088fa12c7730ee6e Mon Sep 17 00:00:00 2001 From: harirubix Date: Thu, 6 Jun 2024 18:13:16 +0530 Subject: [PATCH 055/129] error handling for mnemonicfile --- did/did.go | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/did/did.go b/did/did.go index c123789e..f08c3a69 100644 --- a/did/did.go +++ b/did/did.go @@ -59,6 +59,7 @@ func InitDID(dir string, log logger.Logger, ipfs *ipfsnode.Shell) *DID { func (d *DID) CreateDID(didCreate *DIDCreate) (string, error) { t1 := time.Now() temp := uuid.New() + var _mnemonic []byte dirName := d.dir + temp.String() err := os.MkdirAll(dirName+"/public", os.ModeDir|os.ModePerm) if err != nil { @@ -79,10 +80,14 @@ func (d *DID) CreateDID(didCreate *DIDCreate) (string, error) { return "", err } - _mnemonic, err := os.ReadFile(didCreate.MnemonicFile) - if err != nil { - d.log.Debug("failed to read mnemonic file", "err", err) + _, err := os.Stat(didCreate.MnemonicFile) + if os.IsExist(err) { + _mnemonic, err = os.ReadFile(didCreate.MnemonicFile) + if err != nil { + d.log.Debug("failed to read mnemonic file", "err", err) + } } + var mnemonic string if _mnemonic == nil { mnemonic = crypto.BIPGenerateMnemonic() @@ -260,12 +265,6 @@ func (d *DID) CreateDID(didCreate *DIDCreate) (string, error) { return "", err } - } else if didCreate.Type != LiteDIDMode { - _, err := util.Filecopy(didCreate.PubKeyFile, dirName+"/public/"+PubKeyFileName) - if err != nil { - d.log.Error("failed to copy pub key", "err", err) - return "", err - } } if didCreate.Type == ChildDIDMode { From 0a8efffc85b6444046ad22818f2a2a67451cc216 Mon Sep 17 00:00:00 2001 From: harirubix Date: Thu, 6 Jun 2024 18:44:44 +0530 Subject: [PATCH 056/129] undo unintentional delete --- did/did.go | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/did/did.go b/did/did.go index f08c3a69..aeb6bca9 100644 --- a/did/did.go +++ b/did/did.go @@ -265,6 +265,12 @@ func (d *DID) CreateDID(didCreate *DIDCreate) (string, error) { return "", err } + } else if didCreate.Type != LiteDIDMode { + _, err := util.Filecopy(didCreate.PubKeyFile, dirName+"/public/"+PubKeyFileName) + if err != nil { + d.log.Error("failed to copy pub key", "err", err) + return "", err + } } if didCreate.Type == ChildDIDMode { From 992c505336753608bf00d17824c766ac7e994cd6 Mon Sep 17 00:00:00 2001 From: harirubix Date: Fri, 7 Jun 2024 13:57:19 +0530 Subject: [PATCH 057/129] issue with mnemonickey reading --- did/did.go | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/did/did.go b/did/did.go index aeb6bca9..572badd1 100644 --- a/did/did.go +++ b/did/did.go @@ -81,10 +81,12 @@ func (d *DID) CreateDID(didCreate *DIDCreate) (string, error) { } _, err := os.Stat(didCreate.MnemonicFile) - if os.IsExist(err) { + if os.IsNotExist(err) { + d.log.Debug("mnemonic file does not exist , creating new") + } else { _mnemonic, err = os.ReadFile(didCreate.MnemonicFile) if err != nil { - d.log.Debug("failed to read mnemonic file", "err", err) + d.log.Error("failed to read file", "err", err) } } From f6f667e71e2d17ec7a75828f3b0b1b1f787c3dfd Mon Sep 17 00:00:00 2001 From: Maneesha-rubix Date: Mon, 27 May 2024 17:18:15 +0530 Subject: [PATCH 058/129] register while pinging a peer --- core/core.go | 29 +++++++++++++++++++++++------ core/data_token.go | 2 +- core/migrate.go | 2 +- core/peer.go | 32 +++++++++++++++++++++++++++++++- core/ping.go | 37 +++++++++++++++++++++++++++++++++---- core/quorum_initiator.go | 6 +++--- core/quorum_recv.go | 22 +++++++++++----------- core/quorum_validation.go | 10 +++++----- core/smart_contract.go | 2 +- core/transfer.go | 2 +- core/wallet/did.go | 2 +- 11 files changed, 111 insertions(+), 35 deletions(-) diff --git a/core/core.go b/core/core.go index 537de591..8daadffa 100644 --- a/core/core.go +++ b/core/core.go @@ -526,7 +526,7 @@ func (c *Core) SetupDID(reqID string, didStr string) (did.DIDCrypto, error) { } // Initializes the did in it's corresponding did mode (basic/ lite) -func (c *Core) SetupForienDID(didStr string) (did.DIDCrypto, error) { +func (c *Core) SetupForienDID(didStr string, self_did string) (did.DIDCrypto, error) { err := c.FetchDID(didStr) if err != nil { c.log.Error("couldn't fetch did") @@ -538,16 +538,33 @@ func (c *Core) SetupForienDID(didStr string) (did.DIDCrypto, error) { didtype, err := c.w.GetPeerDIDType(didStr) if err != nil { dt, err1 := c.w.GetDID(didStr) - if err1 != nil { - return nil, fmt.Errorf("couldn't fetch did type") + if err1 != nil || dt.Type == -1 { + peerId := c.w.GetPeerID(didStr) + + if peerId == "" { + return nil, err + } + if self_did != "" { + didtype_, msg, err2 := c.GetPeerdidType_fromPeer(peerId, didStr, self_did) + if err2 != nil { + c.log.Error(msg) + return nil, err2 + } + didtype = didtype_ + peerUpdateResult, err3 := c.w.UpdatePeerDIDType(didStr, didtype) + if !peerUpdateResult { + c.log.Error("couldn't update did type in peer did table", err3) + } + } + } else { + didtype = dt.Type } - didtype = dt.Type } return c.InitialiseDID(didStr, didtype) } // Initializes the quorum in it's corresponding did mode (basic/ lite) -func (c *Core) SetupForienDIDQuorum(didStr string) (did.DIDCrypto, error) { +func (c *Core) SetupForienDIDQuorum(didStr string, self_did string) (did.DIDCrypto, error) { err := c.FetchDID(didStr) if err != nil { return nil, err @@ -565,7 +582,7 @@ func (c *Core) SetupForienDIDQuorum(didStr string) (did.DIDCrypto, error) { if peerId == "" { return nil, err } - didtype_, msg, err2 := c.GetPeerdidType_fromPeer(peerId, didStr) + didtype_, msg, err2 := c.GetPeerdidType_fromPeer(peerId, didStr, self_did) if err2 != nil { c.log.Error(msg) return nil, err2 diff --git a/core/data_token.go b/core/data_token.go index 33f0fc30..3a25f9f1 100644 --- a/core/data_token.go +++ b/core/data_token.go @@ -365,7 +365,7 @@ func (c *Core) CheckDataToken(dt string) bool { return false } did := b.GetDID() - dc, err := c.SetupForienDID(did) + dc, err := c.SetupForienDID(did, "") if err != nil { c.log.Error("failed to setup did crypto") return false diff --git a/core/migrate.go b/core/migrate.go index cd55f0b0..48c155ac 100644 --- a/core/migrate.go +++ b/core/migrate.go @@ -221,7 +221,7 @@ func (c *Core) migrateNode(reqID string, m *MigrateRequest, didDir string) error ha := h.Sum(nil) addr := int(ha[0]) % len(c.arbitaryAddr) c.log.Info("Conneting to node : " + c.arbitaryAddr[addr]) - p, err := c.getPeer(c.arbitaryAddr[addr]) + p, err := c.getPeer(c.arbitaryAddr[addr], "") if err != nil { c.log.Error("Failed to migrate, failed to connect arbitary peer", "err", err, "peer", c.arbitaryAddr[addr]) return fmt.Errorf("failed to migrate, failed to connect arbitary peer") diff --git a/core/peer.go b/core/peer.go index fb9e9cf6..c11ed750 100644 --- a/core/peer.go +++ b/core/peer.go @@ -4,6 +4,7 @@ import ( "encoding/json" "fmt" "net/http" + "strconv" "github.com/rubixchain/rubixgoplatform/core/ipfsport" "github.com/rubixchain/rubixgoplatform/core/model" @@ -63,6 +64,23 @@ func (c *Core) peerCallback(peerID string, topic string, data []byte) { func (c *Core) peerStatus(req *ensweb.Request) *ensweb.Result { did := c.l.GetQuerry(req, "did") + peer_peerid := c.l.GetQuerry(req, "self_peerId") + peer_did := c.l.GetQuerry(req, "self_did") + peer_did_type := c.l.GetQuerry(req, "self_did_type") + + //If the peer's DID type string is not empty, register the peer, if not already registered + if peer_did_type != "" { + peer_did_type_int, err1 := strconv.Atoi(peer_did_type) + if err1 != nil { + c.log.Debug("could not convert string to integer:", err1) + } + + err2 := c.w.AddDIDPeerMap(peer_did, peer_peerid, peer_did_type_int) + if err2 != nil { + c.log.Debug("could not add quorum details to DID peer table:", err2) + } + + } exist := c.w.IsDIDExist(did) ps := model.PeerStatusResponse{ Version: c.version, @@ -71,7 +89,7 @@ func (c *Core) peerStatus(req *ensweb.Request) *ensweb.Result { return c.l.RenderJSON(req, &ps, http.StatusOK) } -func (c *Core) getPeer(addr string) (*ipfsport.Peer, error) { +func (c *Core) getPeer(addr string, self_did string) (*ipfsport.Peer, error) { peerID, did, ok := util.ParseAddress(addr) if !ok { return nil, fmt.Errorf("invalid address") @@ -90,6 +108,18 @@ func (c *Core) getPeer(addr string) (*ipfsport.Peer, error) { } q := make(map[string]string) q["did"] = did + + //share self information to the peer, if required + if self_did != "" { + q["self_peerId"] = c.peerID + q["self_did"] = self_did + self_dt, err := c.w.GetDID(self_did) + if err != nil { + c.log.Info("could not fetch did type of peer:", self_did) + } else { + q["self_did_type"] = strconv.Itoa(self_dt.Type) + } + } var ps model.PeerStatusResponse err = p.SendJSONRequest("GET", APIPeerStatus, q, nil, &ps, false) if err != nil { diff --git a/core/ping.go b/core/ping.go index 4d0731f0..4815d22b 100644 --- a/core/ping.go +++ b/core/ping.go @@ -3,6 +3,7 @@ package core import ( "fmt" "net/http" + "strconv" "time" "github.com/rubixchain/rubixgoplatform/core/model" @@ -107,13 +108,29 @@ func (c *Core) CheckQuorumStatus(peerID string, did string) (string, bool, error // CheckQuorumStatusResponse is the handler for CheckQuorumStatus request func (c *Core) GetPeerdidTypeResponse(req *ensweb.Request) *ensweb.Result { //PingRecevied did := c.l.GetQuerry(req, "did") - c.log.Info("Fetching peer did type from peer") + peer_peerid := c.l.GetQuerry(req, "self_peerid") + peer_did := c.l.GetQuerry(req, "self_did") + peer_did_type := c.l.GetQuerry(req, "self_did_type") + resp := &model.GetDIDTypeResponse{ BasicResponse: model.BasicResponse{ Status: false, }, } + //If the peer's DID type string is not empty, register the peer, if not already registered + if peer_did_type != "" { + peer_did_type_int, err1 := strconv.Atoi(peer_did_type) + if err1 != nil { + c.log.Debug("could not convert string to integer:", err1) + } + + err2 := c.w.AddDIDPeerMap(peer_did, peer_peerid, peer_did_type_int) + if err2 != nil { + c.log.Debug("could not add quorum details to DID peer table:", err2) + } + } + dt, err := c.w.GetDID(did) if err != nil { c.log.Error("Couldn't fetch did type from DID Table", "error", err) @@ -131,16 +148,28 @@ func (c *Core) GetPeerdidTypeResponse(req *ensweb.Request) *ensweb.Result { //Pi } // GetPeerdidType will ping the peer & get the did type -func (c *Core) GetPeerdidType_fromPeer(peerID string, did string) (int, string, error) { +func (c *Core) GetPeerdidType_fromPeer(peerID string, peer_did string, self_DID string) (int, string, error) { q := make(map[string]string) - p, err := c.pm.OpenPeerConn(peerID, did, c.getCoreAppName(peerID)) + p, err := c.pm.OpenPeerConn(peerID, peer_did, c.getCoreAppName(peerID)) if err != nil { return -1, "Quorum Connection Error", fmt.Errorf("quorum connection error") } // Close the p2p before exit defer p.Close() - q["did"] = did + q["did"] = peer_did + + if self_DID != "" { + q["self_peerid"] = c.peerID + q["self_did"] = self_DID + self_dt, err := c.w.GetDID(self_DID) + if err != nil { + c.log.Info("could not fetch did type of peer:", self_DID) + } else { + q["self_did_type"] = strconv.Itoa(self_dt.Type) + } + } + var getPeerdidTypeResponse model.GetDIDTypeResponse err = p.SendJSONRequest("GET", APIGetPeerDIDTypePath, q, nil, &getPeerdidTypeResponse, false, 2*time.Minute) if err != nil { diff --git a/core/quorum_initiator.go b/core/quorum_initiator.go index da5cef74..d488451c 100644 --- a/core/quorum_initiator.go +++ b/core/quorum_initiator.go @@ -398,7 +398,7 @@ func (c *Core) initiateConsensus(cr *ConensusRequest, sc *contract.Contract, dc } } if cr.Mode == RBTTransferMode { - rp, err := c.getPeer(cr.ReceiverPeerID + "." + sc.GetReceiverDID()) + rp, err := c.getPeer(cr.ReceiverPeerID+"."+sc.GetReceiverDID(), "") if err != nil { c.log.Error("Receiver not connected", "err", err) return nil, nil, err @@ -662,7 +662,7 @@ func (c *Core) quorumPledgeFinality(cr *ConensusRequest, newBlock *block.Block) qAddress = quorumValue } } - qPeer, err := c.getPeer(qAddress) + qPeer, err := c.getPeer(qAddress, "") if err != nil { c.log.Error("Quorum not connected", "err", err) return err @@ -759,7 +759,7 @@ func (c *Core) connectQuorum(cr *ConensusRequest, addr string, qt int, sc *contr c.startConsensus(cr.ReqID, qt) var p *ipfsport.Peer var err error - p, err = c.getPeer(addr) + p, err = c.getPeer(addr, sc.GetSenderDID()) if err != nil { c.log.Error("Failed to get peer connection", "err", err) c.finishConsensus(cr.ReqID, qt, nil, false, "", nil, nil) diff --git a/core/quorum_recv.go b/core/quorum_recv.go index f9a6f607..7e45b618 100644 --- a/core/quorum_recv.go +++ b/core/quorum_recv.go @@ -36,10 +36,10 @@ func (c *Core) creditStatus(req *ensweb.Request) *ensweb.Result { return c.l.RenderJSON(req, &cs, http.StatusOK) } -func (c *Core) verifyContract(cr *ConensusRequest) (bool, *contract.Contract) { +func (c *Core) verifyContract(cr *ConensusRequest, self_did string) (bool, *contract.Contract) { sc := contract.InitContract(cr.ContractBlock, nil) // setup the did to verify the signature - dc, err := c.SetupForienDID(sc.GetSenderDID()) + dc, err := c.SetupForienDID(sc.GetSenderDID(), self_did) if err != nil { c.log.Error("Failed to get DID", "err", err) return false, nil @@ -57,7 +57,7 @@ func (c *Core) quorumDTConsensus(req *ensweb.Request, did string, qdc didcrypto. ReqID: cr.ReqID, Status: false, } - ok, sc := c.verifyContract(cr) + ok, sc := c.verifyContract(cr, "") if !ok { crep.Message = "Failed to verify sender signature" return c.l.RenderJSON(req, &crep, http.StatusOK) @@ -70,7 +70,7 @@ func (c *Core) quorumDTConsensus(req *ensweb.Request, did string, qdc didcrypto. return c.l.RenderJSON(req, &crep, http.StatusOK) } address := cr.SenderPeerID + "." + sc.GetSenderDID() - p, err := c.getPeer(address) + p, err := c.getPeer(address, "") if err != nil { c.log.Error("Failed to get peer", "err", err) crep.Message = "Failed to get peer" @@ -108,7 +108,7 @@ func (c *Core) quorumRBTConsensus(req *ensweb.Request, did string, qdc didcrypto ReqID: cr.ReqID, Status: false, } - ok, sc := c.verifyContract(cr) + ok, sc := c.verifyContract(cr, did) if !ok { crep.Message = "Failed to verify sender signature" return c.l.RenderJSON(req, &crep, http.StatusOK) @@ -283,7 +283,7 @@ func (c *Core) quorumNFTSaleConsensus(req *ensweb.Request, did string, qdc didcr ReqID: cr.ReqID, Status: false, } - ok, sc := c.verifyContract(cr) + ok, sc := c.verifyContract(cr, "") if !ok { crep.Message = "Failed to verify sender signature" return c.l.RenderJSON(req, &crep, http.StatusOK) @@ -385,7 +385,7 @@ func (c *Core) quorumSmartContractConsensus(req *ensweb.Request, did string, qdc c.log.Debug("executor did ", verifyDID) } - dc, err := c.SetupForienDID(verifyDID) + dc, err := c.SetupForienDID(verifyDID, did) if err != nil { c.log.Error("Failed to get DID for verification", "err", err) consensusReply.Message = "Failed to get DID for verification" @@ -455,7 +455,7 @@ func (c *Core) quorumSmartContractConsensus(req *ensweb.Request, did string, qdc } else { //sync the smartcontract tokenchain address := consensusRequest.ExecuterPeerID + "." + consensusContract.GetExecutorDID() - peerConn, err := c.getPeer(address) + peerConn, err := c.getPeer(address, did) if err != nil { c.log.Error("Failed to get executor peer to sync smart contract token chain", "err", err) consensusReply.Message = "Failed to get executor peer to sync smart contract token chain : " @@ -645,7 +645,7 @@ func (c *Core) updateReceiverToken(req *ensweb.Request) *ensweb.Result { return c.l.RenderJSON(req, &crep, http.StatusOK) } - p, err := c.getPeer(sr.Address) + p, err := c.getPeer(sr.Address, "") if err != nil { c.log.Error("failed to get peer", "err", err) crep.Message = "failed to get peer" @@ -1190,7 +1190,7 @@ func (c *Core) tokenArbitration(req *ensweb.Request) *ensweb.Result { // return c.l.RenderJSON(req, &srep, http.StatusOK) } if !mflag { - dc, err := c.SetupForienDID(odid) + dc, err := c.SetupForienDID(odid, "") if err != nil { c.log.Error("Failed to do token abitration, failed to setup did crypto", "token", ti[i].Token, "did", odid) srep.Message = "Failed to do token abitration, failed to setup did crypto" @@ -1293,7 +1293,7 @@ func (c *Core) getProofverificationDetails(tokenID string, senderAddr string) (s return "", "", fmt.Errorf("Failed to initilaize previous block") } } else { //if token chain of token pledged for not synced fetch from sender - p, err := c.getPeer(senderAddr) + p, err := c.getPeer(senderAddr, "") if err != nil { c.log.Error("Failed to get peer", "err", err) return "", "", err diff --git a/core/quorum_validation.go b/core/quorum_validation.go index 35613821..bb7397e2 100644 --- a/core/quorum_validation.go +++ b/core/quorum_validation.go @@ -24,7 +24,7 @@ type TokenStateCheckResult struct { tokenIDTokenStateData string } -func (c *Core) validateSigner(b *block.Block) (bool, error) { +func (c *Core) validateSigner(b *block.Block, self_did string) (bool, error) { signers, err := b.GetSigner() if err != nil { c.log.Error("failed to get signers", "err", err) @@ -34,13 +34,13 @@ func (c *Core) validateSigner(b *block.Block) (bool, error) { var dc did.DIDCrypto switch b.GetTransType() { case block.TokenGeneratedType, block.TokenBurntType: - dc, err = c.SetupForienDID(signer) + dc, err = c.SetupForienDID(signer, self_did) if err != nil { c.log.Error("failed to setup foreign DID", "err", err) return false, fmt.Errorf("failed to setup foreign DID : ", signer, "err", err) } default: - dc, err = c.SetupForienDIDQuorum(signer) + dc, err = c.SetupForienDIDQuorum(signer, self_did) if err != nil { c.log.Error("failed to setup foreign DID quorum", "err", err) return false, fmt.Errorf("failed to setup foreign DID quorum : ", signer, "err", err) @@ -150,7 +150,7 @@ func (c *Core) validateTokenOwnership(cr *ConensusRequest, sc *contract.Contract continue } } - p, err := c.getPeer(address) + p, err := c.getPeer(address, quorumDID) if err != nil { c.log.Error("Failed to get peer", "err", err) return false, err @@ -209,7 +209,7 @@ func (c *Core) validateTokenOwnership(cr *ConensusRequest, sc *contract.Contract c.log.Error("Invalid token chain block") return false, fmt.Errorf("Invalid token chain block for ", ti[i].Token) } - signatureValidation, err := c.validateSigner(b) + signatureValidation, err := c.validateSigner(b, quorumDID) if !signatureValidation || err != nil { return false, err } diff --git a/core/smart_contract.go b/core/smart_contract.go index d803b969..b6b9a917 100644 --- a/core/smart_contract.go +++ b/core/smart_contract.go @@ -373,7 +373,7 @@ func (c *Core) ContractCallBack(peerID string, topic string, data []byte) { did := newEvent.Did tokenType := token.SmartContractTokenType address := publisherPeerID + "." + did - p, err := c.getPeer(address) + p, err := c.getPeer(address, "") if err != nil { c.log.Error("Failed to get peer", "err", err) return diff --git a/core/transfer.go b/core/transfer.go index 4c808a61..b65a231c 100644 --- a/core/transfer.go +++ b/core/transfer.go @@ -121,7 +121,7 @@ func (c *Core) initiateRBTTransfer(reqID string, req *model.RBTTransferRequest) } // Get the receiver & do sanity check - p, err := c.getPeer(req.Receiver) + p, err := c.getPeer(req.Receiver, did) if err != nil { resp.Message = "Failed to get receiver peer, " + err.Error() return resp diff --git a/core/wallet/did.go b/core/wallet/did.go index 798bd84a..5df031de 100644 --- a/core/wallet/did.go +++ b/core/wallet/did.go @@ -164,7 +164,7 @@ func (w *Wallet) UpdatePeerDIDType(did string, didtype int) (bool, error) { err1 := w.s.Update(DIDPeerStorage, &dm, "did=?", did) if err1 != nil { - w.log.Error("couldn't update did type in peer did table") + w.log.Error("couldn't update did type in peer did table for:", did) return false, err1 } return true, nil From 6e0dc9102a2360b0dfc8418fe4c141047049445d Mon Sep 17 00:00:00 2001 From: Maneesha-rubix Date: Thu, 6 Jun 2024 14:48:24 +0530 Subject: [PATCH 059/129] sender sharing quorums info with receiver and previous-pledged-quorum info with quorums --- core/core.go | 1 + core/ping.go | 55 ++++++++ core/quorum_initiator.go | 38 ++++++ core/quorum_recv.go | 6 + core/quorum_validation.go | 14 +- tests/config/node_registry.json | 4 +- tests/node/actions.py | 18 ++- tests/node/commands.py | 6 +- tests/node/quorum.py | 14 +- tests/run.py | 6 +- tests/scenarios/bip39_nlss_test.py | 14 -- tests/scenarios/ping_peer_improvement_test.py | 120 ++++++++++++++++++ tests/scenarios/rbt_transfer.py | 14 -- 13 files changed, 260 insertions(+), 50 deletions(-) create mode 100644 tests/scenarios/ping_peer_improvement_test.py diff --git a/core/core.go b/core/core.go index 8daadffa..ece3f3b1 100644 --- a/core/core.go +++ b/core/core.go @@ -48,6 +48,7 @@ const ( APISyncDIDArbitration string = "/api/sync-did-arbitration" APICheckQuorumStatusPath string = "/api/check-quorum-status" APIGetPeerDIDTypePath string = "/api/get-peer-didType" + APIGetPeerInfoPath string = "/api/get-peer-info" ) const ( diff --git a/core/ping.go b/core/ping.go index 4815d22b..e738bc71 100644 --- a/core/ping.go +++ b/core/ping.go @@ -6,7 +6,9 @@ import ( "strconv" "time" + "github.com/rubixchain/rubixgoplatform/core/ipfsport" "github.com/rubixchain/rubixgoplatform/core/model" + "github.com/rubixchain/rubixgoplatform/core/wallet" "github.com/rubixchain/rubixgoplatform/wrapper/ensweb" ) @@ -20,9 +22,15 @@ type PingResponse struct { model.BasicResponse } +type GetPeerInfoResponse struct { + PeerInfo wallet.DIDPeerMap + model.BasicResponse +} + // PingSetup will setup the ping route func (c *Core) PingSetup() { c.l.AddRoute(APIPingPath, "GET", c.PingRecevied) + c.l.AddRoute(APIGetPeerInfoPath, "GET", c.GetPeerInfoResponse) } // CheckQuorumStatusSetup will setup the ping route @@ -177,3 +185,50 @@ func (c *Core) GetPeerdidType_fromPeer(peerID string, peer_did string, self_DID } return getPeerdidTypeResponse.DidType, getPeerdidTypeResponse.Message, nil } + +func (c *Core) GetPeerInfoResponse(req *ensweb.Request) *ensweb.Result { //PingRecevied + //fetch peer details from DIDPeerTable + peerDID := c.l.GetQuerry(req, "did") + + resp := &GetPeerInfoResponse{ + BasicResponse: model.BasicResponse{ + Status: false, + }, + } + var pInfo wallet.DIDPeerMap + + pInfo.PeerID = c.w.GetPeerID(peerDID) + if pInfo.PeerID == "" { + c.log.Error("sender does not have prev pledged quorum in DIDPeerTable", peerDID) + resp.Message = "Couldn't fetch peer id for did: " + peerDID + resp.Status = false + return c.l.RenderJSON(req, &resp, http.StatusOK) + } + + qDidType, err := c.w.GetPeerDIDType(peerDID) + if err != nil || qDidType == -1 { + c.log.Error("could not fetch did type for quorum:", peerDID, "error", err) + pInfo.DIDType = nil + resp.PeerInfo = pInfo + resp.Status = true + resp.Message = "could not fetch did type, only sharing peerId" + return c.l.RenderJSON(req, &resp, http.StatusOK) + } else { + pInfo.DIDType = &qDidType + } + + resp.PeerInfo = pInfo + resp.Status = true + resp.Message = "successfully fetched peer details" + return c.l.RenderJSON(req, &resp, http.StatusOK) + +} + +func (c *Core) GetPeerInfo(p *ipfsport.Peer, peerDID string) (GetPeerInfoResponse, error) { + q := make(map[string]string) + q["did"] = peerDID + + var response GetPeerInfoResponse + err := p.SendJSONRequest("GET", APIGetPeerInfoPath, q, nil, &response, false) + return response, err +} diff --git a/core/quorum_initiator.go b/core/quorum_initiator.go index d488451c..8ea52277 100644 --- a/core/quorum_initiator.go +++ b/core/quorum_initiator.go @@ -105,6 +105,7 @@ type SendTokenRequest struct { TokenInfo []contract.TokenInfo `json:"token_info"` TokenChainBlock []byte `json:"token_chain_block"` QuorumList []string `json:"quorum_list"` + QuorumInfo []QuorumDIDPeerMap `json:"quorum_info"` } type PledgeReply struct { @@ -410,6 +411,43 @@ func (c *Core) initiateConsensus(cr *ConensusRequest, sc *contract.Contract, dc TokenChainBlock: nb.GetBlock(), QuorumList: cr.QuorumList, } + + //fetching quorums' info from PeerDIDTable to share with the receiver + for _, qrm := range sr.QuorumList { + //fetch peer id & did of the quorum + qpid, qdid, ok := util.ParseAddress(qrm) + if !ok { + c.log.Error("could not parse quorum address:", qrm) + } + if qpid == "" { + qpid = c.w.GetPeerID(qdid) + } + + var qrmInfo QuorumDIDPeerMap + //fetch did type of the quorum + qDidType, err := c.w.GetPeerDIDType(qdid) + if err != nil { + c.log.Error("could not fetch did type for quorum:", qdid, "error", err) + } + if qDidType == -1 { + c.log.Info("did type is empty for quorum:", qdid, "connecting & fetching from quorum") + didtype_, msg, err := c.GetPeerdidType_fromPeer(qpid, qdid, dc.GetDID()) + if err != nil { + c.log.Error("error", err, "msg", msg) + qrmInfo.DIDType = nil + } else { + qDidType = didtype_ + qrmInfo.DIDType = &qDidType + } + } else { + qrmInfo.DIDType = &qDidType + } + //add quorum details to the data to be shared + qrmInfo.DID = qdid + qrmInfo.PeerID = qpid + sr.QuorumInfo = append(sr.QuorumInfo, qrmInfo) + } + var br model.BasicResponse err = rp.SendJSONRequest("POST", APISendReceiverToken, nil, &sr, &br, true) if err != nil { diff --git a/core/quorum_recv.go b/core/quorum_recv.go index 7e45b618..68280160 100644 --- a/core/quorum_recv.go +++ b/core/quorum_recv.go @@ -786,6 +786,12 @@ func (c *Core) updateReceiverToken(req *ensweb.Request) *ensweb.Result { c.w.AddTransactionHistory(td) crep.Status = true crep.Message = "Token received successfully" + + //Adding quorums to DIDPeerTable of receiver + for _, qrm := range sr.QuorumInfo { + c.w.AddDIDPeerMap(qrm.DID, qrm.PeerID, *qrm.DIDType) + } + return c.l.RenderJSON(req, &crep, http.StatusOK) } diff --git a/core/quorum_validation.go b/core/quorum_validation.go index bb7397e2..806c507a 100644 --- a/core/quorum_validation.go +++ b/core/quorum_validation.go @@ -24,7 +24,7 @@ type TokenStateCheckResult struct { tokenIDTokenStateData string } -func (c *Core) validateSigner(b *block.Block, self_did string) (bool, error) { +func (c *Core) validateSigner(b *block.Block, self_did string, p *ipfsport.Peer) (bool, error) { signers, err := b.GetSigner() if err != nil { c.log.Error("failed to get signers", "err", err) @@ -40,6 +40,16 @@ func (c *Core) validateSigner(b *block.Block, self_did string) (bool, error) { return false, fmt.Errorf("failed to setup foreign DID : ", signer, "err", err) } default: + signer_peeerId := c.w.GetPeerID(signer) + if signer_peeerId == "" { + signer_details, err := c.GetPeerInfo(p, signer) + if err != nil || signer_details.PeerInfo.PeerID == "" { + c.log.Error("failed to fetch details of the signer", signer, "msg", signer_details.Message) + return signer_details.Status, err + } + signer_details.PeerInfo.DID = signer + c.AddPeerDetails(signer_details.PeerInfo) + } dc, err = c.SetupForienDIDQuorum(signer, self_did) if err != nil { c.log.Error("failed to setup foreign DID quorum", "err", err) @@ -209,7 +219,7 @@ func (c *Core) validateTokenOwnership(cr *ConensusRequest, sc *contract.Contract c.log.Error("Invalid token chain block") return false, fmt.Errorf("Invalid token chain block for ", ti[i].Token) } - signatureValidation, err := c.validateSigner(b, quorumDID) + signatureValidation, err := c.validateSigner(b, quorumDID, p) if !signatureValidation || err != nil { return false, err } diff --git a/tests/config/node_registry.json b/tests/config/node_registry.json index 08c4e27b..db63da27 100644 --- a/tests/config/node_registry.json +++ b/tests/config/node_registry.json @@ -1,5 +1,7 @@ { "quorum": [4, 5, 6, 7, 8], "rbt_transfer": [9, 10], - "bip39_nlss": [11, 12] + "bip39_nlss": [11, 12], + "quorum2": [13, 14, 15, 16, 17], + "ping_peer": [18,19] } \ No newline at end of file diff --git a/tests/node/actions.py b/tests/node/actions.py index dd8854f3..6cb33ef4 100644 --- a/tests/node/actions.py +++ b/tests/node/actions.py @@ -3,11 +3,19 @@ from .utils import get_node_name_from_idx, get_did_by_alias from config.utils import save_to_config_file, get_node_registry -def add_quorums(node_config: dict): - for config in node_config.values(): +def add_quorums(node_config: dict, node_key = "", quorumlist = "quorumlist.json"): + if node_key == "": + for config in node_config.values(): + cmd_add_quorum_dids( + config["server"], + config["grpcPort"] + ) + else: + config = node_config[node_key] cmd_add_quorum_dids( config["server"], - config["grpcPort"] + config["grpcPort"], + quorumlist ) def setup_quorums(node_config: dict, node_did_alias_map: dict): @@ -19,11 +27,11 @@ def setup_quorums(node_config: dict, node_did_alias_map: dict): config["grpcPort"] ) -def quorum_config(node_config: dict, node_did_alias_map: dict, skip_adding_quorums: bool = False): +def quorum_config(node_config: dict, node_did_alias_map: dict, skip_adding_quorums: bool = False, quorum_list_file_name = "quorumlist.json"): # Prepare quorumlist.json quorum_list = [] build_dir = get_build_dir() - quorum_list_file_path = f"../{build_dir}/quorumlist.json" + quorum_list_file_path = f"../{build_dir}/{quorum_list_file_name}" if skip_adding_quorums: setup_quorums(node_config, node_did_alias_map) diff --git a/tests/node/commands.py b/tests/node/commands.py index a44fd0d7..90ff2ff2 100644 --- a/tests/node/commands.py +++ b/tests/node/commands.py @@ -155,11 +155,11 @@ def cmd_generate_rbt(did_id, numTokens, server_port, grpc_port): os.chdir("../tests") return output -def cmd_add_quorum_dids(server_port, grpc_port): +def cmd_add_quorum_dids(server_port, grpc_port, quorumlist = "quorumlist.json"): os.chdir("../" + get_build_dir()) - cmd_string = f"./rubixgoplatform addquorum -port {server_port} -grpcPort {grpc_port}" + cmd_string = f"./rubixgoplatform addquorum -port {server_port} -grpcPort {grpc_port} -quorumList {quorumlist}" if is_windows_os(): - cmd_string = f".\\rubixgoplatform addquorum -port {server_port} -grpcPort {grpc_port}" + cmd_string = f".\\rubixgoplatform addquorum -port {server_port} -grpcPort {grpc_port} -quorumList {quorumlist}" output, code = run_command(cmd_string, True) print(output) if code != 0: diff --git a/tests/node/quorum.py b/tests/node/quorum.py index 51e8792c..48e19d03 100644 --- a/tests/node/quorum.py +++ b/tests/node/quorum.py @@ -7,9 +7,8 @@ QUORUM_CONFIG_PATH = "./quorum_config.json" -def run_quorum_nodes(only_run_nodes, skip_adding_quorums): +def run_quorum_nodes(only_run_nodes, skip_adding_quorums, node_registry_key = "quorum", quorum_config_path = "./quorum_config.json", quorum_list_file_name = "quorumlist.json"): print("Running Rubix Quorum nodes......") - node_registry_key = "quorum" node_config = setup_rubix_nodes(node_registry_key) print("Rubix Quorum nodes are now running") @@ -27,21 +26,18 @@ def run_quorum_nodes(only_run_nodes, skip_adding_quorums): node_did_alias_map[node] = did_alias #Temporary adding details manually - for _, val1 in node_config.items(): - for _, val2 in node_config.items(): - add_peer_details(val1["peerId"], val1["dids"]["did_quorum"], 4, val2["server"], val2["grpcPort"]) - save_to_config_file(QUORUM_CONFIG_PATH, node_config) - print("\nquorum_config.json is created") + save_to_config_file(quorum_config_path, node_config) + print("\nquorum_config json file is created") print("Setting up quorums and saving the info in quorumlist.json") - quorum_config(node_config, node_did_alias_map, skip_adding_quorums=skip_adding_quorums) + quorum_config(node_config, node_did_alias_map, skip_adding_quorums, quorum_list_file_name) pprint.pp(node_config) print("Quorums have been configured") else: - quorum_config(node_config, node_did_alias_map, skip_adding_quorums=True) + quorum_config(node_config, node_did_alias_map, True, quorum_list_file_name) def get_quorum_config(): return load_from_config_file(QUORUM_CONFIG_PATH) diff --git a/tests/run.py b/tests/run.py index 67f3705f..73cc9022 100644 --- a/tests/run.py +++ b/tests/run.py @@ -8,7 +8,8 @@ from scenarios import ( rbt_transfer, - bip39_nlss_test + bip39_nlss_test, + ping_peer_improvement_test ) IPFS_KUBO_VERSION = "v0.21.0" @@ -164,7 +165,8 @@ def cli(): # that consists of logic to run all the necessary tests modules = [ rbt_transfer, - bip39_nlss_test + bip39_nlss_test, + ping_peer_improvement_test ] for module in modules: diff --git a/tests/scenarios/bip39_nlss_test.py b/tests/scenarios/bip39_nlss_test.py index 50c3e0d2..c4991195 100644 --- a/tests/scenarios/bip39_nlss_test.py +++ b/tests/scenarios/bip39_nlss_test.py @@ -53,19 +53,6 @@ def nlss_to_bip39(node_config): expect_success(fund_did_with_rbt)(node_nlss, did_nlss, 3) print("Funded NLSS DID with 3 RBT") - #adding peer details of bip39 node and nlss node to quorums - add_peer_details(node_bip39["peerId"], did_bip39, 4, 20004, 10504) - add_peer_details(node_bip39["peerId"], did_bip39, 4, 20005, 10505) - add_peer_details(node_bip39["peerId"], did_bip39, 4, 20006, 10506) - add_peer_details(node_bip39["peerId"], did_bip39, 4, 20007, 10507) - add_peer_details(node_bip39["peerId"], did_bip39, 4, 20008, 10508) - - add_peer_details(node_nlss["peerId"], did_nlss, 0, 20004, 10504) - add_peer_details(node_nlss["peerId"], did_nlss, 0, 20005, 10505) - add_peer_details(node_nlss["peerId"], did_nlss, 0, 20006, 10506) - add_peer_details(node_nlss["peerId"], did_nlss, 0, 20007, 10507) - add_peer_details(node_nlss["peerId"], did_nlss, 0, 20008, 10508) - quorum_config = get_quorum_config() for _, val in quorum_config.items(): @@ -99,7 +86,6 @@ def bip39_to_nlss(node_config): print("------ Test Case (PASS): Transferring whole, part and mix RBT from BIP39 DID to NLSS DID ------\n") print("\n4. Transferring 0.5 RBT from BIP39 DID to NLSS DID....") - add_peer_details(node_nlss["peerId"], did_nlss, 0, server_port_bip39, grpc_port_bip39) #adding peer details of nlss node to bip39 expect_success(rbt_transfer)(did_bip39, did_nlss, 0.5, server_port_bip39, grpc_port_bip39) print("Transferred 0.5 RBT from BIP39 DID to NLSS DID") diff --git a/tests/scenarios/ping_peer_improvement_test.py b/tests/scenarios/ping_peer_improvement_test.py new file mode 100644 index 00000000..040631bc --- /dev/null +++ b/tests/scenarios/ping_peer_improvement_test.py @@ -0,0 +1,120 @@ +from node.actions import rbt_transfer, fund_did_with_rbt, setup_rubix_nodes, \ + create_and_register_did, add_quorums, add_peer_details +from node.utils import get_did_by_alias +from config.utils import save_to_config_file, load_from_config_file +from helper.utils import expect_failure, expect_success +from node.quorum import get_quorum_config, run_quorum_nodes + +__node_config_path = "./ping_peer_config.json" + +def setup(): + print("Setting up ping peer improvement test.....") + print("Configuring and running node18 and node19...") + + node_config = setup_rubix_nodes("ping_peer") + + config_A = node_config["node18"] + config_B = node_config["node19"] + + create_and_register_did(config_A, "did_a", register_did=False) + create_and_register_did(config_B, "did_b", register_did=False) + + save_to_config_file(__node_config_path, node_config) + + run_quorum_nodes(False, False, "quorum2", "./quorum_config2.json", "quorumlist2.json") + + print("Adding quorums for A") + add_quorums(node_config, "node18") + + print("Adding quorums for B") + add_quorums(node_config, "node19", "quorumlist2.json") + + print("Setup Done\n") + return node_config + +def run(skip_setup: bool = False): + print("\n----------- 1. Running Tests related to ping peer improvement -----------\n") + node_config = {} + + # In some cases, we may wish to run tests for an existing test configuration + # where the nodes are running already. If skip_setup is True, the setup steps + # are skipped and we proceed to directly run the test cases and load the config + # from the config file + if not skip_setup: + node_config = setup() + else: + node_config = load_from_config_file(__node_config_path) + + shuttle_transfer(node_config) + + print("\n-------------- Tests Completed -------------------\n") + +def shuttle_transfer(config): + node_A_info, node_B_info = config["node18"], config["node19"] + server_port_A, grpc_port_A = node_A_info["server"], node_A_info["grpcPort"] + server_port_B, grpc_port_B = node_B_info["server"], node_B_info["grpcPort"] + did_A, did_B = get_did_by_alias(node_A_info, "did_a"), get_did_by_alias(node_B_info, "did_b") + + print("------ Test Case (PASS): Shuttle transfer started ------\n") + + quorum_config = get_quorum_config() + + for _, val in quorum_config.items(): + add_peer_details(val["peerId"], val["dids"]["did_quorum"], 4, server_port_A, grpc_port_A) + + quorum_config2 = load_from_config_file("./quorum_config2.json") + for _, val in quorum_config2.items(): + add_peer_details(val["peerId"], val["dids"]["did_quorum"], 4, server_port_B, grpc_port_B) + + + print("\n1. Generating 3 whole RBT for A") + expect_success(fund_did_with_rbt)(node_A_info, did_A, 3) + print("Funded node A with 2 RBT") + + print("\n2. Transferring 0.5 RBT from A to B....") + add_peer_details(node_B_info["peerId"], did_B, 4, server_port_A, grpc_port_A) #adding peer details of node B to node A + expect_success(rbt_transfer)(did_A, did_B, 0.5, server_port_A, grpc_port_A) + print("Transferred 0.5 RBT from A to B") + + print("\n4. Transferring 0.25 RBT from B to A....") + add_peer_details(node_A_info["peerId"], did_A, 4, server_port_B, grpc_port_B) #adding peer details of node A to node B + expect_success(rbt_transfer)(did_B, did_A, 0.25, server_port_B, grpc_port_B) + print("Transferred 0.25 RBT from B to A") + + print("\n3. Transferring 1.499 RBT from A to B....") + expect_success(rbt_transfer)(did_A, did_B, 1.499, server_port_A, grpc_port_A) + print("Transferred 1.499 RBT from A to B") + + print("\n5. Transferring 0.25 RBT from B to A....") + expect_success(rbt_transfer)(did_B, did_A, 0.25, server_port_B, grpc_port_B) + print("Transferred 0.25 RBT from B to A") + + print("\n6. Transferring 0.25 RBT from B to A....") + expect_success(rbt_transfer)(did_B, did_A, 0.25, server_port_B, grpc_port_B) + print("Transferred 0.25 RBT from B to A") + + print("\n8. Transferring 1 RBT from A to B....") + expect_success(rbt_transfer)(did_A, did_B, 1, server_port_A, grpc_port_A) + print("Transferred 1 RBT from A to B") + + print("\n7. Transferring 0.25 RBT from B to A....") + expect_success(rbt_transfer)(did_B, did_A, 0.25, server_port_B, grpc_port_B) + print("Transferred 0.25 RBT from B to A") + + print("\n9. Generating 2 whole RBT for A") + expect_success(fund_did_with_rbt)(node_A_info, did_A, 2) + print("Funded node A with 2 RBT") + + print("\n10. Transferring 2 RBT from A to B....") + expect_success(rbt_transfer)(did_A, did_B, 2, server_port_A, grpc_port_A) + print("Transferred 2 RBT from A to B") + + print("\n11. Transferring 0.001 RBT from A to B....") + expect_success(rbt_transfer)(did_A, did_B, 0.001, server_port_A, grpc_port_A) + print("Transferred 0.001 RBT from A to B") + + print("\n7. Transferring 1.25 RBT from B to A....") + expect_success(rbt_transfer)(did_B, did_A, 1.25, server_port_B, grpc_port_B) + print("Transferred 0.25 RBT from B to A") + + print("\n------ Test Case (PASS): Shuttle transfer completed ------\n") diff --git a/tests/scenarios/rbt_transfer.py b/tests/scenarios/rbt_transfer.py index b47b1208..b9622c9f 100644 --- a/tests/scenarios/rbt_transfer.py +++ b/tests/scenarios/rbt_transfer.py @@ -86,24 +86,10 @@ def shuttle_transfer(config): print("------ Test Case (PASS): Shuttle transfer started ------\n") - #adding peer details of node A and node B to quorums - add_peer_details(node_A_info["peerId"], did_A, 4, 20004, 10504) - add_peer_details(node_A_info["peerId"], did_A, 4, 20005, 10505) - add_peer_details(node_A_info["peerId"], did_A, 4, 20006, 10506) - add_peer_details(node_A_info["peerId"], did_A, 4, 20007, 10507) - add_peer_details(node_A_info["peerId"], did_A, 4, 20008, 10508) - - add_peer_details(node_B_info["peerId"], did_B, 4, 20004, 10504) - add_peer_details(node_B_info["peerId"], did_B, 4, 20005, 10505) - add_peer_details(node_B_info["peerId"], did_B, 4, 20006, 10506) - add_peer_details(node_B_info["peerId"], did_B, 4, 20007, 10507) - add_peer_details(node_B_info["peerId"], did_B, 4, 20008, 10508) - quorum_config = get_quorum_config() for _, val in quorum_config.items(): add_peer_details(val["peerId"], val["dids"]["did_quorum"], 4, server_port_A, grpc_port_A) - add_peer_details(val["peerId"], val["dids"]["did_quorum"], 4, server_port_B, grpc_port_B) print("\n1. Generating 2 whole RBT for A") expect_success(fund_did_with_rbt)(node_A_info, did_A, 2) From 0590554fc849f7ac0cdc1ffe851ce55529e6aa79 Mon Sep 17 00:00:00 2001 From: harirubix Date: Wed, 12 Jun 2024 01:13:33 +0530 Subject: [PATCH 060/129] parse did to get cid digest and use this to calc lastchar --- core/wallet/did.go | 30 ++++++++++++++++++++++++++---- 1 file changed, 26 insertions(+), 4 deletions(-) diff --git a/core/wallet/did.go b/core/wallet/did.go index 798bd84a..410ae4f3 100644 --- a/core/wallet/did.go +++ b/core/wallet/did.go @@ -1,5 +1,11 @@ package wallet +import ( + "encoding/hex" + + "github.com/ipfs/go-cid" +) + type DIDType struct { DID string `gorm:"column:did;primaryKey"` Type int `gorm:"column:type"` @@ -84,9 +90,17 @@ func (w *Wallet) IsDIDExist(did string) bool { } func (w *Wallet) AddDIDPeerMap(did string, peerID string, didType int) error { - lastChar := string(did[len(did)-1]) + // Parse the did + c, err := cid.Decode(did) + if err != nil { + w.log.Error("Failed to decode DID: %v", err) + } + multihashDigest := c.Hash() + // Convert the multihash digest to hexadecimal - to compare with txnID + hexDigest := hex.EncodeToString(multihashDigest) + lastChar := string(hexDigest[len(hexDigest)-1]) var dm DIDPeerMap - err := w.s.Read(DIDStorage, &dm, "did=?", did) + err = w.s.Read(DIDStorage, &dm, "did=?", did) if err == nil { return nil } @@ -117,9 +131,17 @@ func (w *Wallet) AddDIDLastChar() error { } for _, dm := range existingDIDPeer { did := dm.DID - lastChar := string(did[len(did)-1]) + // Parse the did + c, err := cid.Decode(did) + if err != nil { + w.log.Error("Failed to decode DID: %v", err) + } + multihashDigest := c.Hash() + // Convert the multihash digest to hexadecimal - to compare with txnID + hexDigest := hex.EncodeToString(multihashDigest) + lastChar := string(hexDigest[len(hexDigest)-1]) dm.DIDLastChar = lastChar - err := w.s.Update(DIDPeerStorage, &dm, "did=?", did) + err = w.s.Update(DIDPeerStorage, &dm, "did=?", did) w.log.Info("DID Peer table updated") if err != nil { w.log.Error("Unable to update DID Peer table.") From 9de8aabd652958bf3cd2ab8819f40f850c06bd14 Mon Sep 17 00:00:00 2001 From: Vaishnav CH Date: Wed, 12 Jun 2024 01:58:11 +0530 Subject: [PATCH 061/129] Change from single qrm tokens unlock to all qrms tokens unlock --- core/quorum_initiator.go | 44 +++++++++++++++++++--------------------- 1 file changed, 21 insertions(+), 23 deletions(-) diff --git a/core/quorum_initiator.go b/core/quorum_initiator.go index 7c0f1b19..4c7c0f39 100644 --- a/core/quorum_initiator.go +++ b/core/quorum_initiator.go @@ -394,7 +394,7 @@ func (c *Core) initiateConsensus(cr *ConensusRequest, sc *contract.Contract, dc } } if err != nil { - unlockErr := c.checkLokedTokens(cr, ql) + unlockErr := c.checkLockedTokens(cr, ql) if unlockErr != nil { c.log.Error(unlockErr.Error() + "Locked tokens could not be unlocked") } @@ -1375,35 +1375,33 @@ func (c *Core) createCommitedTokensBlock(newBlock *block.Block, smartContractTok return nil } -func (c *Core) checkLokedTokens(cr *ConensusRequest, quorumList []string) error { - // var err error +func (c *Core) checkLockedTokens(cr *ConensusRequest, quorumList []string) error { pd := c.pd[cr.ReqID] pledgingQuorumDID := make([]string, 0, len(pd.PledgedTokens)) for k := range pd.PledgedTokens { pledgingQuorumDID = append(pledgingQuorumDID, k) } - var pledgingDID string - if len(pledgingQuorumDID) > 0 { - pledgingDID = pledgingQuorumDID[0] - } + var br model.BasicResponse - for _, addr := range quorumList { - peerID, did, _ := util.ParseAddress(addr) - if did == pledgingDID { - p, err := c.pm.OpenPeerConn(peerID, did, c.getCoreAppName(peerID)) - if err != nil { - c.log.Error("Failed to get peer connection", "err", err) - return err - } - tokenList := TokenList{ - Tokens: pd.PledgedTokens[pledgingDID], - DID: pledgingDID, - } - err = p.SendJSONRequest("POST", APIUnlockTokens, nil, &tokenList, &br, true) - if err != nil { - c.log.Error("Invalid response for pledge request", "err", err) - return err + for _, pledgingDID := range pledgingQuorumDID { + for _, addr := range quorumList { + peerID, did, _ := util.ParseAddress(addr) + if did == pledgingDID { + p, err := c.pm.OpenPeerConn(peerID, did, c.getCoreAppName(peerID)) + if err != nil { + c.log.Error("Failed to get peer connection", "err", err) + return err + } + tokenList := TokenList{ + Tokens: pd.PledgedTokens[pledgingDID], + DID: pledgingDID, + } + err = p.SendJSONRequest("POST", APIUnlockTokens, nil, &tokenList, &br, true) + if err != nil { + c.log.Error("Invalid response for pledge request", "err", err) + return err + } } } } From f54bd206c89ebbe0cf5dd0cd6da9e05bcf0bf96d Mon Sep 17 00:00:00 2001 From: Maneesha-rubix Date: Wed, 12 Jun 2024 14:28:22 +0530 Subject: [PATCH 062/129] adding ping-peer-improvement test cases to rbt-transfer test cases --- tests/config/node_registry.json | 3 +- tests/run.py | 2 - tests/scenarios/ping_peer_improvement_test.py | 120 ------------------ tests/scenarios/rbt_transfer.py | 15 ++- 4 files changed, 13 insertions(+), 127 deletions(-) delete mode 100644 tests/scenarios/ping_peer_improvement_test.py diff --git a/tests/config/node_registry.json b/tests/config/node_registry.json index db63da27..be41c287 100644 --- a/tests/config/node_registry.json +++ b/tests/config/node_registry.json @@ -2,6 +2,5 @@ "quorum": [4, 5, 6, 7, 8], "rbt_transfer": [9, 10], "bip39_nlss": [11, 12], - "quorum2": [13, 14, 15, 16, 17], - "ping_peer": [18,19] + "quorum2": [13, 14, 15, 16, 17] } \ No newline at end of file diff --git a/tests/run.py b/tests/run.py index 73cc9022..2a3cce09 100644 --- a/tests/run.py +++ b/tests/run.py @@ -9,7 +9,6 @@ from scenarios import ( rbt_transfer, bip39_nlss_test, - ping_peer_improvement_test ) IPFS_KUBO_VERSION = "v0.21.0" @@ -166,7 +165,6 @@ def cli(): modules = [ rbt_transfer, bip39_nlss_test, - ping_peer_improvement_test ] for module in modules: diff --git a/tests/scenarios/ping_peer_improvement_test.py b/tests/scenarios/ping_peer_improvement_test.py deleted file mode 100644 index 040631bc..00000000 --- a/tests/scenarios/ping_peer_improvement_test.py +++ /dev/null @@ -1,120 +0,0 @@ -from node.actions import rbt_transfer, fund_did_with_rbt, setup_rubix_nodes, \ - create_and_register_did, add_quorums, add_peer_details -from node.utils import get_did_by_alias -from config.utils import save_to_config_file, load_from_config_file -from helper.utils import expect_failure, expect_success -from node.quorum import get_quorum_config, run_quorum_nodes - -__node_config_path = "./ping_peer_config.json" - -def setup(): - print("Setting up ping peer improvement test.....") - print("Configuring and running node18 and node19...") - - node_config = setup_rubix_nodes("ping_peer") - - config_A = node_config["node18"] - config_B = node_config["node19"] - - create_and_register_did(config_A, "did_a", register_did=False) - create_and_register_did(config_B, "did_b", register_did=False) - - save_to_config_file(__node_config_path, node_config) - - run_quorum_nodes(False, False, "quorum2", "./quorum_config2.json", "quorumlist2.json") - - print("Adding quorums for A") - add_quorums(node_config, "node18") - - print("Adding quorums for B") - add_quorums(node_config, "node19", "quorumlist2.json") - - print("Setup Done\n") - return node_config - -def run(skip_setup: bool = False): - print("\n----------- 1. Running Tests related to ping peer improvement -----------\n") - node_config = {} - - # In some cases, we may wish to run tests for an existing test configuration - # where the nodes are running already. If skip_setup is True, the setup steps - # are skipped and we proceed to directly run the test cases and load the config - # from the config file - if not skip_setup: - node_config = setup() - else: - node_config = load_from_config_file(__node_config_path) - - shuttle_transfer(node_config) - - print("\n-------------- Tests Completed -------------------\n") - -def shuttle_transfer(config): - node_A_info, node_B_info = config["node18"], config["node19"] - server_port_A, grpc_port_A = node_A_info["server"], node_A_info["grpcPort"] - server_port_B, grpc_port_B = node_B_info["server"], node_B_info["grpcPort"] - did_A, did_B = get_did_by_alias(node_A_info, "did_a"), get_did_by_alias(node_B_info, "did_b") - - print("------ Test Case (PASS): Shuttle transfer started ------\n") - - quorum_config = get_quorum_config() - - for _, val in quorum_config.items(): - add_peer_details(val["peerId"], val["dids"]["did_quorum"], 4, server_port_A, grpc_port_A) - - quorum_config2 = load_from_config_file("./quorum_config2.json") - for _, val in quorum_config2.items(): - add_peer_details(val["peerId"], val["dids"]["did_quorum"], 4, server_port_B, grpc_port_B) - - - print("\n1. Generating 3 whole RBT for A") - expect_success(fund_did_with_rbt)(node_A_info, did_A, 3) - print("Funded node A with 2 RBT") - - print("\n2. Transferring 0.5 RBT from A to B....") - add_peer_details(node_B_info["peerId"], did_B, 4, server_port_A, grpc_port_A) #adding peer details of node B to node A - expect_success(rbt_transfer)(did_A, did_B, 0.5, server_port_A, grpc_port_A) - print("Transferred 0.5 RBT from A to B") - - print("\n4. Transferring 0.25 RBT from B to A....") - add_peer_details(node_A_info["peerId"], did_A, 4, server_port_B, grpc_port_B) #adding peer details of node A to node B - expect_success(rbt_transfer)(did_B, did_A, 0.25, server_port_B, grpc_port_B) - print("Transferred 0.25 RBT from B to A") - - print("\n3. Transferring 1.499 RBT from A to B....") - expect_success(rbt_transfer)(did_A, did_B, 1.499, server_port_A, grpc_port_A) - print("Transferred 1.499 RBT from A to B") - - print("\n5. Transferring 0.25 RBT from B to A....") - expect_success(rbt_transfer)(did_B, did_A, 0.25, server_port_B, grpc_port_B) - print("Transferred 0.25 RBT from B to A") - - print("\n6. Transferring 0.25 RBT from B to A....") - expect_success(rbt_transfer)(did_B, did_A, 0.25, server_port_B, grpc_port_B) - print("Transferred 0.25 RBT from B to A") - - print("\n8. Transferring 1 RBT from A to B....") - expect_success(rbt_transfer)(did_A, did_B, 1, server_port_A, grpc_port_A) - print("Transferred 1 RBT from A to B") - - print("\n7. Transferring 0.25 RBT from B to A....") - expect_success(rbt_transfer)(did_B, did_A, 0.25, server_port_B, grpc_port_B) - print("Transferred 0.25 RBT from B to A") - - print("\n9. Generating 2 whole RBT for A") - expect_success(fund_did_with_rbt)(node_A_info, did_A, 2) - print("Funded node A with 2 RBT") - - print("\n10. Transferring 2 RBT from A to B....") - expect_success(rbt_transfer)(did_A, did_B, 2, server_port_A, grpc_port_A) - print("Transferred 2 RBT from A to B") - - print("\n11. Transferring 0.001 RBT from A to B....") - expect_success(rbt_transfer)(did_A, did_B, 0.001, server_port_A, grpc_port_A) - print("Transferred 0.001 RBT from A to B") - - print("\n7. Transferring 1.25 RBT from B to A....") - expect_success(rbt_transfer)(did_B, did_A, 1.25, server_port_B, grpc_port_B) - print("Transferred 0.25 RBT from B to A") - - print("\n------ Test Case (PASS): Shuttle transfer completed ------\n") diff --git a/tests/scenarios/rbt_transfer.py b/tests/scenarios/rbt_transfer.py index b9622c9f..436b06f2 100644 --- a/tests/scenarios/rbt_transfer.py +++ b/tests/scenarios/rbt_transfer.py @@ -3,7 +3,7 @@ from node.utils import get_did_by_alias from config.utils import save_to_config_file, load_from_config_file from helper.utils import expect_failure, expect_success -from node.quorum import get_quorum_config +from node.quorum import get_quorum_config, run_quorum_nodes __node_config_path = "./rbt_transfer_config.json" @@ -21,8 +21,13 @@ def setup(): save_to_config_file(__node_config_path, node_config) - print("Adding quorums") - add_quorums(node_config) + run_quorum_nodes(False, False, "quorum2", "./quorum_config2.json", "quorumlist2.json") + + print("Adding quorums for A") + add_quorums(node_config, "node9") + + print("Adding quorums for B") + add_quorums(node_config, "node10", "quorumlist2.json") print("Setup Done\n") return node_config @@ -91,6 +96,10 @@ def shuttle_transfer(config): for _, val in quorum_config.items(): add_peer_details(val["peerId"], val["dids"]["did_quorum"], 4, server_port_A, grpc_port_A) + quorum_config2 = load_from_config_file("./quorum_config2.json") + for _, val in quorum_config2.items(): + add_peer_details(val["peerId"], val["dids"]["did_quorum"], 4, server_port_B, grpc_port_B) + print("\n1. Generating 2 whole RBT for A") expect_success(fund_did_with_rbt)(node_A_info, did_A, 2) print("Funded node A with 2 RBT") From 083c9b1ce1965e5b88551f7504a4a8098f63f220 Mon Sep 17 00:00:00 2001 From: Vaishnav CH Date: Wed, 12 Jun 2024 15:39:34 +0530 Subject: [PATCH 063/129] Remove extra codes and optimization --- core/quorum_initiator.go | 26 +++++--------------------- 1 file changed, 5 insertions(+), 21 deletions(-) diff --git a/core/quorum_initiator.go b/core/quorum_initiator.go index 4c7c0f39..8c8a07ea 100644 --- a/core/quorum_initiator.go +++ b/core/quorum_initiator.go @@ -748,15 +748,6 @@ func (c *Core) finishConsensus(id string, qt int, p *ipfsport.Peer, status bool, } return } - pledgingQuorumDID := make([]string, 0, len(pd.PledgedTokens)) - for k := range pd.PledgedTokens { - pledgingQuorumDID = append(pledgingQuorumDID, k) - } - var pledgingDID string - if len(pledgingQuorumDID) > 0 { - pledgingDID = pledgingQuorumDID[0] - } - var signType string //signType = 0 => Pki based sign in lite mode @@ -779,19 +770,12 @@ func (c *Core) finishConsensus(id string, qt int, p *ipfsport.Peer, status bool, Hash: hash, SignType: signType, } - if cs.Result.SuccessCount < MinConsensusRequired-1 { - cs.P[did] = p - cs.Credit.Credit = append(cs.Credit.Credit, csig) - cs.Result.SuccessCount++ - if did == pledgingDID { - cs.Result.PledgingDIDSignStatus = true + if cs.Result.SuccessCount < MinConsensusRequired { + if _, ok := pd.PledgedTokens[did]; ok { + cs.P[did] = p + cs.Credit.Credit = append(cs.Credit.Credit, csig) + cs.Result.SuccessCount++ } - } else if (did == pledgingDID || cs.Result.PledgingDIDSignStatus) && cs.Result.SuccessCount == MinConsensusRequired-1 { - cs.P[did] = p - cs.Credit.Credit = append(cs.Credit.Credit, csig) - cs.Result.SuccessCount++ - } else { - p.Close() } } else { cs.Result.FailedCount++ From ac7ec7a6924ae48b780f9871bf7930981bb2f85e Mon Sep 17 00:00:00 2001 From: Vaishnav CH Date: Wed, 12 Jun 2024 15:40:06 +0530 Subject: [PATCH 064/129] Fix typo error --- core/quorum_recv.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/quorum_recv.go b/core/quorum_recv.go index a3b55428..26dc51f1 100644 --- a/core/quorum_recv.go +++ b/core/quorum_recv.go @@ -1343,7 +1343,7 @@ func (c *Core) unlockTokens(req *ensweb.Request) *ensweb.Result { } crep.Status = true crep.Message = "Tokens Unlocked Successfully." - c.log.Info("Tokens Unclocked") + c.log.Info("Tokens Unlocked") return c.l.RenderJSON(req, &crep, http.StatusOK) } From 16662370d85944ec2085fa72e31aece724d46d29 Mon Sep 17 00:00:00 2001 From: Ashita Gupta Date: Fri, 14 Jun 2024 13:27:42 +0530 Subject: [PATCH 065/129] updated return error --- core/wallet/did.go | 34 ++++++++++++++++++++-------------- 1 file changed, 20 insertions(+), 14 deletions(-) diff --git a/core/wallet/did.go b/core/wallet/did.go index 410ae4f3..66b86055 100644 --- a/core/wallet/did.go +++ b/core/wallet/did.go @@ -2,6 +2,7 @@ package wallet import ( "encoding/hex" + "fmt" "github.com/ipfs/go-cid" ) @@ -90,15 +91,10 @@ func (w *Wallet) IsDIDExist(did string) bool { } func (w *Wallet) AddDIDPeerMap(did string, peerID string, didType int) error { - // Parse the did - c, err := cid.Decode(did) + lastChar, err := w.GetLastChar(did) if err != nil { - w.log.Error("Failed to decode DID: %v", err) + return err } - multihashDigest := c.Hash() - // Convert the multihash digest to hexadecimal - to compare with txnID - hexDigest := hex.EncodeToString(multihashDigest) - lastChar := string(hexDigest[len(hexDigest)-1]) var dm DIDPeerMap err = w.s.Read(DIDStorage, &dm, "did=?", did) if err == nil { @@ -131,15 +127,10 @@ func (w *Wallet) AddDIDLastChar() error { } for _, dm := range existingDIDPeer { did := dm.DID - // Parse the did - c, err := cid.Decode(did) + lastChar, err := w.GetLastChar(did) if err != nil { - w.log.Error("Failed to decode DID: %v", err) + continue } - multihashDigest := c.Hash() - // Convert the multihash digest to hexadecimal - to compare with txnID - hexDigest := hex.EncodeToString(multihashDigest) - lastChar := string(hexDigest[len(hexDigest)-1]) dm.DIDLastChar = lastChar err = w.s.Update(DIDPeerStorage, &dm, "did=?", did) w.log.Info("DID Peer table updated") @@ -150,6 +141,21 @@ func (w *Wallet) AddDIDLastChar() error { } return nil } + +func (w *Wallet) GetLastChar(did string) (string, error) { + // Parse the did + c, err := cid.Decode(did) + if err != nil { + w.log.Error(fmt.Sprintf("Failed to decode DID %v : %v", did, err)) + return "", err + } + multihashDigest := c.Hash() + // Convert the multihash digest to hexadecimal - to compare with txnID + hexDigest := hex.EncodeToString(multihashDigest) + lastchar := string(hexDigest[len(hexDigest)-1]) + return lastchar, nil +} + func (w *Wallet) GetPeerID(did string) string { var dm DIDPeerMap err := w.s.Read(DIDPeerStorage, &dm, "did=?", did) From a0a4b52c5f1789597f6d6021621b1513e0dcf50a Mon Sep 17 00:00:00 2001 From: Maneesha-rubix Date: Mon, 17 Jun 2024 11:49:05 +0530 Subject: [PATCH 066/129] fix smart contract deploy error --- core/quorum_initiator.go | 32 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/core/quorum_initiator.go b/core/quorum_initiator.go index ca6af25b..22525055 100644 --- a/core/quorum_initiator.go +++ b/core/quorum_initiator.go @@ -1018,22 +1018,6 @@ func (c *Core) pledgeQuorumToken(cr *ConensusRequest, sc *contract.Contract, tid } //tokenList = append(tokenList, cr.PartTokens...) - //Fetching sender signature to add it to transaction details - senderdid := sc.GetSenderDID() - sign_data, sender_share_sign, sender_priv_sign, err := sc.GetHashSig(senderdid) - if err != nil { - c.log.Error("failed to fetch sender sign", "err", err) - return nil, fmt.Errorf("failed to fetch sender sign") - } - sender_sign_type := dc.GetSignType() - sender_sign := &block.SenderSignature{ - NLSS_share: sender_share_sign, - Private_sign: sender_priv_sign, - DID: senderdid, - Hash: sign_data, - SignType: sender_sign_type, - } - var tcb block.TokenChainBlock if cr.Mode == SmartContractDeployMode { @@ -1083,6 +1067,22 @@ func (c *Core) pledgeQuorumToken(cr *ConensusRequest, sc *contract.Contract, tid SmartContractData: sc.GetSmartContractData(), } } else { + //Fetching sender signature to add it to transaction details + senderdid := sc.GetSenderDID() + sign_data, sender_share_sign, sender_priv_sign, err := sc.GetHashSig(senderdid) + if err != nil { + c.log.Error("failed to fetch sender sign", "err", err) + return nil, fmt.Errorf("failed to fetch sender sign") + } + sender_sign_type := dc.GetSignType() + sender_sign := &block.SenderSignature{ + NLSS_share: sender_share_sign, + Private_sign: sender_priv_sign, + DID: senderdid, + Hash: sign_data, + SignType: sender_sign_type, + } + bti.SenderDID = sc.GetSenderDID() bti.ReceiverDID = sc.GetReceiverDID() tcb = block.TokenChainBlock{ From e43aa468ebdc26863db11a5d35d242d0374687e2 Mon Sep 17 00:00:00 2001 From: Ashita Gupta Date: Tue, 18 Jun 2024 18:01:25 +0530 Subject: [PATCH 067/129] adding pledged token state details at quorum side --- client/token.go | 24 ++++++++++ command/command.go | 8 ++++ command/tokenstate.go | 37 ++++++++++++++ core/model/tokens.go | 15 +++++- core/quorum_initiator.go | 98 ++++++++++++++++++++++++++------------ core/quorum_recv.go | 22 +++++++++ core/quorum_validation.go | 2 + core/token.go | 44 +++++++++++++---- core/wallet/token.go | 97 +++++++++++++++++++++++++++++++++++++ core/wallet/token_chain.go | 7 +++ core/wallet/wallet.go | 7 +++ grpcserver/token.go | 2 +- server/server.go | 2 + server/tokens.go | 41 ++++++++++++++++ setup/setup.go | 2 + 15 files changed, 366 insertions(+), 42 deletions(-) create mode 100644 command/tokenstate.go diff --git a/client/token.go b/client/token.go index d5c56bec..0bbd9668 100644 --- a/client/token.go +++ b/client/token.go @@ -1,6 +1,8 @@ package client import ( + "time" + "github.com/rubixchain/rubixgoplatform/core/model" "github.com/rubixchain/rubixgoplatform/setup" ) @@ -29,3 +31,25 @@ func (c *Client) GetAllTokens(didStr string, tokenType string) (*model.TokenResp } return &tr, nil } + +func (c *Client) GetPledgedTokenDetails() (*model.TokenStateResponse, error) { + var tr model.TokenStateResponse + err := c.sendJSONRequest("GET", setup.APIGetPledgedTokenDetails, nil, nil, &tr, time.Minute*2) + if err != nil { + c.log.Error("Failed to get pledged token details", "err", err) + return nil, err + } + return &tr, nil +} + +func (c *Client) GetPinnedInfo(TokenStateHash string) (*model.BasicResponse, error) { + m := make(map[string]string) + m["tokenstatehash"] = TokenStateHash + var br model.BasicResponse + err := c.sendJSONRequest("GET", setup.APICheckPinnedState, m, nil, &br, time.Minute*2) + if err != nil { + c.log.Error("Failed to get Pins", "err", err) + return nil, err + } + return &br, nil +} diff --git a/command/command.go b/command/command.go index e2d9e850..73b0db96 100644 --- a/command/command.go +++ b/command/command.go @@ -82,6 +82,8 @@ const ( AddExplorerCmd string = "addexplorer" RemoveExplorerCmd string = "removeexplorer" GetAllExplorerCmd string = "getallexplorer" + GetPledgedTokenDetailsCmd string = "getpledgedtokendetails" + CheckPinnedState string = "checkpinnedstate" ) var commands = []string{VersionCmd, @@ -249,6 +251,7 @@ type Command struct { links []string mnemonicFile string ChildPath int + TokenState string } func showVersion() { @@ -445,6 +448,7 @@ func Run(args []string) { flag.BoolVar(&cmd.latest, "latest", false, "flag to set latest") flag.StringVar(&cmd.quorumAddr, "quorumAddr", "", "Quorum Node Address to check the status of the Quorum") flag.StringVar(&links, "links", "", "Explorer url") + flag.StringVar(&cmd.TokenState, "tokenstatehash", "", "Give Token State Hash to check state") if len(os.Args) < 2 { fmt.Println("Invalid Command") @@ -602,6 +606,10 @@ func Run(args []string) { cmd.removeExplorer() case GetAllExplorerCmd: cmd.getAllExplorer() + case GetPledgedTokenDetailsCmd: + cmd.GetPledgedTokenDetails() + case CheckPinnedState: + cmd.CheckPinnedState() default: cmd.log.Error("Invalid command") } diff --git a/command/tokenstate.go b/command/tokenstate.go new file mode 100644 index 00000000..4dd26906 --- /dev/null +++ b/command/tokenstate.go @@ -0,0 +1,37 @@ +package command + +import "fmt" + +func (cmd *Command) GetPledgedTokenDetails() { + info, err := cmd.c.GetPledgedTokenDetails() + if err != nil { + cmd.log.Error("Invalid response from the node", "err", err) + return + } + fmt.Printf("Response : %v\n", info) + if !info.Status { + cmd.log.Error("Failed to get account info", "message", info.Message) + } else { + cmd.log.Info("Successfully got the pledged token states info") + fmt.Println("DID ", "Pledged Token ", "Token State") + for _, i := range info.PledgedTokenStateDetails { + fmt.Println(i.DID, " ", i.TokensPledged, " ", i.TokenStateHash) + } + } +} + +//command will take token hash, check for ipfs pinning, if no, ignore, if yes, get token detail, unpledge. + +func (cmd *Command) CheckPinnedState() { + info, err := cmd.c.GetPinnedInfo(cmd.TokenState) + if err != nil { + cmd.log.Error("Invalid response from the node", "err", err) + return + } + fmt.Printf("Response : %v\n", info) + if !info.Status { + cmd.log.Error("Pin not available", "message", info.Message) + } else { + cmd.log.Info("Token State is Pinned") + } +} diff --git a/core/model/tokens.go b/core/model/tokens.go index 8640917a..70022ec2 100644 --- a/core/model/tokens.go +++ b/core/model/tokens.go @@ -42,12 +42,23 @@ type DIDAccountInfo struct { LockedRBT float64 `json:"locked_rbt"` } -type TokenDetial struct { +type TokenDetail struct { Token string `json:"token"` Status int `json:"status"` } type TokenResponse struct { BasicResponse - TokenDetials []TokenDetial `json:"token_detials"` + TokenDetails []TokenDetail `json:"token_detials"` +} + +type PledgedTokenStateDetails struct { + DID string `json:"did"` + TokensPledged string `json:"token"` + TokenStateHash string `json:"token_state"` +} + +type TokenStateResponse struct { + BasicResponse + PledgedTokenStateDetails []PledgedTokenStateDetails `json:"token_state_details"` } diff --git a/core/quorum_initiator.go b/core/quorum_initiator.go index ca6af25b..add5461d 100644 --- a/core/quorum_initiator.go +++ b/core/quorum_initiator.go @@ -1,6 +1,7 @@ package core import ( + "bytes" "errors" "fmt" "strconv" @@ -8,6 +9,7 @@ import ( "sync" "time" + ipfsnode "github.com/ipfs/go-ipfs-api" "github.com/rubixchain/rubixgoplatform/block" "github.com/rubixchain/rubixgoplatform/contract" "github.com/rubixchain/rubixgoplatform/core/ipfsport" @@ -95,9 +97,11 @@ type SignatureReply struct { } type UpdatePledgeRequest struct { - Mode int `json:"mode"` - PledgedTokens []string `json:"pledged_tokens"` - TokenChainBlock []byte `json:"token_chain_block"` + Mode int `json:"mode"` + PledgedTokens []string `json:"pledged_tokens"` + TokenChainBlock []byte `json:"token_chain_block"` + TransferredTokenStateHashes []string `json:"transferred_tokenstate_hash"` + TransactionID string `json:"transaction_id"` } type SendTokenRequest struct { @@ -478,9 +482,25 @@ func (c *Core) initiateConsensus(cr *ConensusRequest, sc *contract.Contract, dc c.log.Error("Unable to send tokens to receiver", "msg", br.Message) return nil, nil, fmt.Errorf("unable to send tokens to receiver, " + br.Message) } + // br.Result will contain the new token state after sending tokens to receiver - //trigger pledge finality to the quorum - pledgeFinalityError := c.quorumPledgeFinality(cr, nb) + newtokenhashresult, ok := br.Result.([]interface{}) + if !ok { + fmt.Println("Type assertion to string failed") + return nil, nil, err + } + var newtokenhashes []string + for i, v := range newtokenhashresult { + statehash, ok := v.(string) + if !ok { + fmt.Println("Type assertion to string failed at index", i) + return nil, nil, err + } + newtokenhashes = append(newtokenhashes, statehash) + } + + //trigger pledge finality to the quorum and also adding the tokenstate hash details to quorum + pledgeFinalityError := c.quorumPledgeFinality(cr, nb, newtokenhashes) if pledgeFinalityError != nil { c.log.Error("Pledge finlaity not achieved", "err", err) return nil, nil, pledgeFinalityError @@ -528,7 +548,7 @@ func (c *Core) initiateConsensus(cr *ConensusRequest, sc *contract.Contract, dc } //trigger pledge finality to the quorum - pledgeFinalityError := c.quorumPledgeFinality(cr, nb) + pledgeFinalityError := c.quorumPledgeFinality(cr, nb, nil) if pledgeFinalityError != nil { c.log.Error("Pledge finlaity not achieved", "err", err) return nil, nil, pledgeFinalityError @@ -573,8 +593,14 @@ func (c *Core) initiateConsensus(cr *ConensusRequest, sc *contract.Contract, dc return nil, nil, err } - //trigger pledge finality to the quorum - pledgeFinalityError := c.quorumPledgeFinality(cr, nb) + //Latest Smart contract token hash after being deployed. + scTokenStateData := cr.SmartContractToken + newBlockId + tokenIDTokenStateBuffer := bytes.NewBuffer([]byte(scTokenStateData)) + newtokenIDTokenStateHash, err := c.ipfs.Add(tokenIDTokenStateBuffer, ipfsnode.Pin(false), ipfsnode.OnlyHash(true)) + c.log.Info(fmt.Sprintf("New smart contract token hash after being deployed : %s", newtokenIDTokenStateHash)) + + //trigger pledge finality to the quorum and adding the details in token hash table + pledgeFinalityError := c.quorumPledgeFinality(cr, nb, []string{newtokenIDTokenStateHash}) if pledgeFinalityError != nil { c.log.Error("Pledge finlaity not achieved", "err", err) return nil, nil, pledgeFinalityError @@ -625,8 +651,14 @@ func (c *Core) initiateConsensus(cr *ConensusRequest, sc *contract.Contract, dc return nil, nil, err } - //trigger pledge finality to the quorum - pledgeFinalityError := c.quorumPledgeFinality(cr, nb) + //Latest Smart contract token hash after being executed. + scTokenStateData := cr.SmartContractToken + newBlockId + tokenIDTokenStateBuffer := bytes.NewBuffer([]byte(scTokenStateData)) + newtokenIDTokenStateHash, err := c.ipfs.Add(tokenIDTokenStateBuffer, ipfsnode.Pin(false), ipfsnode.OnlyHash(true)) + c.log.Info(fmt.Sprintf("New smart contract token hash after being executed : %s", newtokenIDTokenStateHash)) + + //trigger pledge finality to the quorum and adding the details in token hash table + pledgeFinalityError := c.quorumPledgeFinality(cr, nb, []string{newtokenIDTokenStateHash}) if pledgeFinalityError != nil { c.log.Error("Pledge finlaity not achieved", "err", err) return nil, nil, pledgeFinalityError @@ -659,7 +691,7 @@ func (c *Core) initiateConsensus(cr *ConensusRequest, sc *contract.Contract, dc } } -func (c *Core) quorumPledgeFinality(cr *ConensusRequest, newBlock *block.Block) error { +func (c *Core) quorumPledgeFinality(cr *ConensusRequest, newBlock *block.Block, newTokenStateHashes []string) error { c.log.Debug("Proceeding for pledge finality") c.qlock.Lock() pd, ok1 := c.pd[cr.ReqID] @@ -694,9 +726,16 @@ func (c *Core) quorumPledgeFinality(cr *ConensusRequest, newBlock *block.Block) defer qPeer.Close() var br model.BasicResponse ur := UpdatePledgeRequest{ - Mode: cr.Mode, - PledgedTokens: v, - TokenChainBlock: newBlock.GetBlock(), + Mode: cr.Mode, + PledgedTokens: v, + TokenChainBlock: newBlock.GetBlock(), + TransactionID: cr.TransactionID, + TransferredTokenStateHashes: nil, + } + + if newTokenStateHashes != nil { + // ur.TransferredTokenStateHashes = newTokenStateHashes[countofTokenStateHash : countofTokenStateHash+len(v)] + ur.TransferredTokenStateHashes = newTokenStateHashes } err = qPeer.SendJSONRequest("POST", APIUpdatePledgeToken, nil, &ur, &br, true) @@ -1018,22 +1057,6 @@ func (c *Core) pledgeQuorumToken(cr *ConensusRequest, sc *contract.Contract, tid } //tokenList = append(tokenList, cr.PartTokens...) - //Fetching sender signature to add it to transaction details - senderdid := sc.GetSenderDID() - sign_data, sender_share_sign, sender_priv_sign, err := sc.GetHashSig(senderdid) - if err != nil { - c.log.Error("failed to fetch sender sign", "err", err) - return nil, fmt.Errorf("failed to fetch sender sign") - } - sender_sign_type := dc.GetSignType() - sender_sign := &block.SenderSignature{ - NLSS_share: sender_share_sign, - Private_sign: sender_priv_sign, - DID: senderdid, - Hash: sign_data, - SignType: sender_sign_type, - } - var tcb block.TokenChainBlock if cr.Mode == SmartContractDeployMode { @@ -1083,6 +1106,21 @@ func (c *Core) pledgeQuorumToken(cr *ConensusRequest, sc *contract.Contract, tid SmartContractData: sc.GetSmartContractData(), } } else { + //Fetching sender signature to add it to transaction details + senderdid := sc.GetSenderDID() + sign_data, sender_share_sign, sender_priv_sign, err := sc.GetHashSig(senderdid) + if err != nil { + c.log.Error("failed to fetch sender sign", "err", err) + return nil, fmt.Errorf("failed to fetch sender sign") + } + sender_sign_type := dc.GetSignType() + sender_sign := &block.SenderSignature{ + NLSS_share: sender_share_sign, + Private_sign: sender_priv_sign, + DID: senderdid, + Hash: sign_data, + SignType: sender_sign_type, + } bti.SenderDID = sc.GetSenderDID() bti.ReceiverDID = sc.GetReceiverDID() tcb = block.TokenChainBlock{ diff --git a/core/quorum_recv.go b/core/quorum_recv.go index a3b55428..ac1c3d82 100644 --- a/core/quorum_recv.go +++ b/core/quorum_recv.go @@ -779,6 +779,18 @@ func (c *Core) updateReceiverToken(req *ensweb.Request) *ensweb.Result { crep.Message = "Failed to update token status, failed to get block ID" return c.l.RenderJSON(req, &crep, http.StatusOK) } + //add to ipfs to get latest Token State Hash after receiving the token by receiver. The hashes will be returned to sender, and from there to + //quorums using pledgefinality function, to be added to TokenStateHash Table + var updatedtokenhashes []string + for _, ti := range sr.TokenInfo { + t := ti.Token + b := c.w.GetLatestTokenBlock(ti.Token, ti.TokenType) + blockId, _ := b.GetBlockID(t) + tokenIDTokenStateData := t + blockId + tokenIDTokenStateBuffer := bytes.NewBuffer([]byte(tokenIDTokenStateData)) + tokenIDTokenStateHash, _ := c.ipfs.Add(tokenIDTokenStateBuffer, ipfsnode.Pin(false), ipfsnode.OnlyHash(true)) + updatedtokenhashes = append(updatedtokenhashes, tokenIDTokenStateHash) + } td := &wallet.TransactionDetails{ TransactionID: b.GetTid(), TransactionType: b.GetTransType(), @@ -794,6 +806,7 @@ func (c *Core) updateReceiverToken(req *ensweb.Request) *ensweb.Result { c.w.AddTransactionHistory(td) crep.Status = true crep.Message = "Token received successfully" + crep.Result = updatedtokenhashes return c.l.RenderJSON(req, &crep, http.StatusOK) } @@ -939,6 +952,15 @@ func (c *Core) updatePledgeToken(req *ensweb.Request) *ensweb.Result { } } + //Adding to the Token State Hash Table + if ur.TransferredTokenStateHashes != nil { + err = c.w.AddTokenStateHash(did, ur.TransferredTokenStateHashes, ur.PledgedTokens, ur.TransactionID) + } + if err != nil { + c.log.Error("Failed to add token state hash", "err", err) + } + + //TODO : Unpledging tokens to be removed for _, t := range ur.PledgedTokens { c.up.AddUnPledge(t) } diff --git a/core/quorum_validation.go b/core/quorum_validation.go index 4ed027cb..afc33ef8 100644 --- a/core/quorum_validation.go +++ b/core/quorum_validation.go @@ -22,6 +22,7 @@ type TokenStateCheckResult struct { Error error Message string tokenIDTokenStateData string + tokenIDTokenStateHash string } func (c *Core) validateSigner(b *block.Block) (bool, error) { @@ -329,6 +330,7 @@ func (c *Core) checkTokenState(tokenId, did string, index int, resultArray []Tok //add to ipfs get only the hash of the token+tokenstate tokenIDTokenStateHash, err := c.ipfs.Add(tokenIDTokenStateBuffer, ipfsnode.Pin(false), ipfsnode.OnlyHash(true)) + result.tokenIDTokenStateHash = tokenIDTokenStateHash if err != nil { c.log.Error("Error adding data to ipfs", err) result.Error = err diff --git a/core/token.go b/core/token.go index f031727e..2d757b43 100644 --- a/core/token.go +++ b/core/token.go @@ -51,39 +51,39 @@ func (c *Core) GetAllTokens(did string, tt string) (*model.TokenResponse, error) if err != nil { return tr, nil } - tr.TokenDetials = make([]model.TokenDetial, 0) + tr.TokenDetails = make([]model.TokenDetail, 0) for _, t := range tkns { - td := model.TokenDetial{ + td := model.TokenDetail{ Token: t.TokenID, Status: t.TokenStatus, } - tr.TokenDetials = append(tr.TokenDetials, td) + tr.TokenDetails = append(tr.TokenDetails, td) } case model.DTType: tkns, err := c.w.GetAllDataTokens(did) if err != nil { return tr, nil } - tr.TokenDetials = make([]model.TokenDetial, 0) + tr.TokenDetails = make([]model.TokenDetail, 0) for _, t := range tkns { - td := model.TokenDetial{ + td := model.TokenDetail{ Token: t.TokenID, Status: t.TokenStatus, } - tr.TokenDetials = append(tr.TokenDetials, td) + tr.TokenDetails = append(tr.TokenDetails, td) } case model.NFTType: tkns := c.w.GetAllNFT(did) if tkns == nil { return tr, nil } - tr.TokenDetials = make([]model.TokenDetial, 0) + tr.TokenDetails = make([]model.TokenDetail, 0) for _, t := range tkns { - td := model.TokenDetial{ + td := model.TokenDetail{ Token: t.TokenID, Status: t.TokenStatus, } - tr.TokenDetials = append(tr.TokenDetials, td) + tr.TokenDetails = append(tr.TokenDetails, td) } default: tr.BasicResponse.Status = false @@ -490,3 +490,29 @@ func (c *Core) GetRequiredTokens(did string, txnAmount float64) ([]wallet.Token, remainingAmount = floatPrecision(remainingAmount, MaxDecimalPlaces) return requiredTokens, remainingAmount, nil } + +func (c *Core) GetPledgedInfo() ([]model.PledgedTokenStateDetails, error) { + wt, err := c.w.GetAllTokenStateHash() + if err != nil && err.Error() != "no records found" { + c.log.Error("Failed to get token state hashes", "err", err) + return []model.PledgedTokenStateDetails{}, fmt.Errorf("failed to get token states") + } + info := []model.PledgedTokenStateDetails{} + for _, t := range wt { + k := model.PledgedTokenStateDetails{ + DID: t.DID, + TokensPledged: t.PledgedTokens, + TokenStateHash: t.TokenStateHash, + } + info = append(info, k) + } + return info, nil +} + +func (c *Core) UpdatePledgedTokenInfo(tokenstatehash string) error { + err := c.w.RemoveTokenStateHash(tokenstatehash) + if err != nil && err.Error() != "no records found" { + c.log.Error("Failed to get token state hash", "err", err) + } + return nil +} diff --git a/core/wallet/token.go b/core/wallet/token.go index 7bfad11b..711afd31 100644 --- a/core/wallet/token.go +++ b/core/wallet/token.go @@ -3,6 +3,7 @@ package wallet import ( "fmt" "os" + "strings" "github.com/rubixchain/rubixgoplatform/block" "github.com/rubixchain/rubixgoplatform/contract" @@ -593,3 +594,99 @@ func (w *Wallet) UnlockLockedTokens(did string, tokenList []string) error { } return nil } + +func (w *Wallet) AddTokenStateHash(did string, tokenstatehashes []string, pledgedtokens []string, TransactionID string) error { + w.l.Lock() + defer w.l.Unlock() + var td TokenStateDetails + if tokenstatehashes == nil { + return nil + } + concatenatedpledgedtokens := "" + + for _, i := range pledgedtokens { + concatenatedpledgedtokens = concatenatedpledgedtokens + i + " " + } + + for _, tokenstatehash := range tokenstatehashes { + td.DID = did + td.PledgedTokens = concatenatedpledgedtokens + td.TokenStateHash = tokenstatehash + td.TransactionID = TransactionID + err := w.s.Write(TokenStateHash, &td) + if err != nil { + w.log.Error("Token State Hash could not be added", "token state hash", tokenstatehash, "err", err) + return err + } + } + return nil +} + +func (w *Wallet) GetAllTokenStateHash() ([]TokenStateDetails, error) { + var td []TokenStateDetails + err := w.s.Read(TokenStateHash, &td, "did!=?", "") + if err != nil { + w.log.Error("Failed to get token states", "err", err) + return nil, err + } + return td, nil +} + +func (w *Wallet) RemoveTokenStateHash(tokenstatehash string) error { + var td TokenStateDetails + + //Getting all the details about a particular token state hash + err := w.s.Read(TokenStateHash, &td, "token_state_hash=?", tokenstatehash) + if err != nil { + w.log.Error("Failed to fetch token state from DB", "err", err) + return err + } + + // Using that token state hash to get the Transaction ID. Now fetch all the entries with that Transaction ID. + + var tds []TokenStateDetails + + err = w.s.Read(TokenStateHash, &tds, "transaction_id=?", td.TransactionID) + if err != nil { + w.log.Error("Failed to fetch token state from DB", "err", err) + return err + } + + // If length of entries with same Transaction ID is more than 1, this means all the token state hashes of that particular transaction are not exhausted. + // So, we'll remove just that entry with the exhausted token state. If the length is 1, this means, only this Token State Hash was left to be exhausted, + // and thus, the quorums can unpledge their tokens. + + if len(tds) > 1 { + err = w.s.Delete(TokenStateHash, &td, "token_state_hash=?", tokenstatehash) + if err != nil { + w.log.Error("Failed to delete token state hash details from DB", "err", err) + return err + } + return nil + } + + pledgedTokensList := strings.Split(td.PledgedTokens, " ") + + for _, v := range pledgedTokensList { + var tokend Token + err = w.s.Read(TokenStorage, &tokend, "did=? AND token_id=?", td.DID, v) + if err != nil { + w.log.Error("Failed to read token details from DB", "err", err) + return err + } + tokend.TokenStatus = TokenIsFree + err = w.s.Update(TokenStorage, &tokend, "did=? AND token_id=?", tokend.DID, tokend.TokenID) + if err != nil { + w.log.Error("Failed to update token status from DB", "err", err) + return err + } + } + var td1 TokenStateDetails + err = w.s.Delete(TokenStateHash, &td1, "token_state_hash=?", tokenstatehash) + if err != nil { + w.log.Error("Failed to delete token state from DB", "err", err) + return err + } + fmt.Println("Delete TokenStateDetails : ", td1) + return nil +} diff --git a/core/wallet/token_chain.go b/core/wallet/token_chain.go index 5d3060d8..84ec1c43 100644 --- a/core/wallet/token_chain.go +++ b/core/wallet/token_chain.go @@ -34,6 +34,13 @@ const ( const TCBlockCountLimit int = 100 +type TokenStateDetails struct { + DID string `gorm:"column:did" json:"did"` + TokenStateHash string `gorm:"column:token_state_hash;primaryKey" json:"token_state_hash"` + PledgedTokens string `gorm:"column:pledged_token" json:"pledged_token"` + TransactionID string `gorm:"column:transaction_id" json:"transaction_id"` +} + func tcsType(tokenType int) string { tt := "wt" switch tokenType { diff --git a/core/wallet/wallet.go b/core/wallet/wallet.go index f0a0666b..bfa6eb32 100644 --- a/core/wallet/wallet.go +++ b/core/wallet/wallet.go @@ -27,6 +27,7 @@ const ( SmartContractTokenChainStorage string = "smartcontractokenchainstorage" SmartContractStorage string = "smartcontract" CallBackUrlStorage string = "callbackurl" + TokenStateHash string = "TokenStateHashTable" ) type WalletConfig struct { @@ -149,6 +150,12 @@ func InitWallet(s storage.Storage, dir string, log logger.Logger) (*Wallet, erro return nil, err } + err = w.s.Init(TokenStateHash, &TokenStateDetails{}, true) + if err != nil { + w.log.Error("Failed to initialize TokenStateHash", "err", err) + return nil, err + } + return w, nil } diff --git a/grpcserver/token.go b/grpcserver/token.go index 28eb8fdd..a32526f9 100644 --- a/grpcserver/token.go +++ b/grpcserver/token.go @@ -87,7 +87,7 @@ func (rn *RubixNative) GetAllTokens(ctx context.Context, in *protos.TokenReq) (* resp := &protos.TokenResp{ TokenDetials: make([]*protos.TokenDetial, 0), } - for _, td := range tr.TokenDetials { + for _, td := range tr.TokenDetails { t := &protos.TokenDetial{ Token: td.Token, TokenState: int32(td.Status), diff --git a/server/server.go b/server/server.go index b16b6ef1..a06930e0 100644 --- a/server/server.go +++ b/server/server.go @@ -161,6 +161,8 @@ func (s *Server) RegisterRoutes() { s.AddRoute(setup.APIGetAllExplorer, "GET", s.AuthHandle(s.APIGetAllExplorer, false, s.AuthError, true)) s.AddRoute(setup.APIAddExplorer, "POST", s.AuthHandle(s.APIAddExplorer, false, s.AuthError, true)) s.AddRoute(setup.APIRemoveExplorer, "POST", s.AuthHandle(s.APIRemoveExplorer, false, s.AuthError, true)) + s.AddRoute(setup.APIGetPledgedTokenDetails, "GET", s.AuthHandle(s.APIGetPledgedTokenDetails, false, s.AuthError, true)) + s.AddRoute(setup.APICheckPinnedState, "GET", s.AuthHandle(s.APICheckPinnedState, false, s.AuthError, true)) } func (s *Server) ExitFunc() error { diff --git a/server/tokens.go b/server/tokens.go index 5db737c4..516ee89c 100644 --- a/server/tokens.go +++ b/server/tokens.go @@ -130,3 +130,44 @@ func (s *Server) APISignatureResponse(req *ensweb.Request) *ensweb.Result { dc.InChan <- resp return s.didResponse(req, resp.ID) } + +func (s *Server) APIGetPledgedTokenDetails(req *ensweb.Request) *ensweb.Result { + pledgedTokenInfo, err := s.c.GetPledgedInfo() + if err != nil { + return s.BasicResponse(req, false, err.Error(), nil) + } + tokenstateresponse := model.TokenStateResponse{ + BasicResponse: model.BasicResponse{ + Status: true, + Message: "Got pledged tokens with token states info successfully", + }, + PledgedTokenStateDetails: make([]model.PledgedTokenStateDetails, 0), + } + tokenstateresponse.PledgedTokenStateDetails = append(tokenstateresponse.PledgedTokenStateDetails, pledgedTokenInfo...) + return s.RenderJSON(req, tokenstateresponse, http.StatusOK) +} + +func (s *Server) APICheckPinnedState(req *ensweb.Request) *ensweb.Result { + tokenstatehash := s.GetQuerry(req, "tokenstatehash") + + provList, err := s.c.GetDHTddrs(tokenstatehash) + if err != nil { + return s.BasicResponse(req, false, err.Error(), nil) + } + var br model.BasicResponse + if len(provList) == 0 { + br.Status = false + br.Message = "No pins available on " + tokenstatehash + return s.RenderJSON(req, br, http.StatusOK) + } else { + br.Status = true + br.Result = provList + } + + err = s.c.UpdatePledgedTokenInfo(tokenstatehash) + if err != nil { + return s.BasicResponse(req, false, err.Error(), nil) + } + br.Message = "Got Pins on " + tokenstatehash + ". Updated the pledging detail in table and removed from pledged token state table." + return s.RenderJSON(req, br, http.StatusOK) +} diff --git a/setup/setup.go b/setup/setup.go index 5aa8b15d..acd82084 100644 --- a/setup/setup.go +++ b/setup/setup.go @@ -67,6 +67,8 @@ const ( APIGetAllExplorer string = "/api/get-all-explorer" APIAddExplorer string = "/api/add-explorer" APIRemoveExplorer string = "/api/remove-explorer" + APIGetPledgedTokenDetails string = "/api/get-pledgedtoken-details" + APICheckPinnedState string = "/api/check-pinned-state" ) // jwt.RegisteredClaims From 35d19980a373a1ae2b4726c86fc2cf052be2e3ec Mon Sep 17 00:00:00 2001 From: Vaishnav CH Date: Wed, 19 Jun 2024 15:33:02 +0530 Subject: [PATCH 068/129] Add `QuorumRequired` const. and change in `GetFinalQuorumList()` func --- core/diagnostic.go | 4 ++-- core/quorum_initiator.go | 3 ++- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/core/diagnostic.go b/core/diagnostic.go index f4eaa9ff..27e0a981 100644 --- a/core/diagnostic.go +++ b/core/diagnostic.go @@ -213,8 +213,8 @@ func (c *Core) GetFinalQuorumList(ql []string) ([]string, error) { var finalQl []string var opError error // Loop through ql in groups of the Minimum Quorum Required - for i := 0; i < len(ql); i += MinQuorumRequired { - end := i + MinQuorumRequired + for i := 0; i < len(ql); i += QuorumRequired { + end := i + QuorumRequired if end > len(ql) { end = len(ql) } diff --git a/core/quorum_initiator.go b/core/quorum_initiator.go index 8c8a07ea..fa1d1211 100644 --- a/core/quorum_initiator.go +++ b/core/quorum_initiator.go @@ -18,6 +18,7 @@ import ( ) const ( + QuorumRequired int = 7 MinQuorumRequired int = 5 MinConsensusRequired int = 5 ) @@ -343,7 +344,7 @@ func (c *Core) initiateConsensus(cr *ConensusRequest, sc *contract.Contract, dc return nil, nil, errFQL } cr.QuorumList = finalQl - if len(finalQl) != MinQuorumRequired { + if len(finalQl) != QuorumRequired { c.log.Error("quorum(s) are unavailable for this trnx") return nil, nil, fmt.Errorf("quorum(s) are unavailable for this trnx. retry trnx after some time") } From 9da8b3325dc54a375baccd48673a7dedba9b7fb9 Mon Sep 17 00:00:00 2001 From: Vaishnav CH Date: Wed, 19 Jun 2024 16:29:07 +0530 Subject: [PATCH 069/129] Update quorum unavailability error --- core/quorum_initiator.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/quorum_initiator.go b/core/quorum_initiator.go index fa1d1211..0985203d 100644 --- a/core/quorum_initiator.go +++ b/core/quorum_initiator.go @@ -344,7 +344,7 @@ func (c *Core) initiateConsensus(cr *ConensusRequest, sc *contract.Contract, dc return nil, nil, errFQL } cr.QuorumList = finalQl - if len(finalQl) != QuorumRequired { + if len(finalQl) < MinQuorumRequired { c.log.Error("quorum(s) are unavailable for this trnx") return nil, nil, fmt.Errorf("quorum(s) are unavailable for this trnx. retry trnx after some time") } From 971e79495ab4e8ce3671e4afe4ff6aa15a1d8df2 Mon Sep 17 00:00:00 2001 From: Vaishnav CH Date: Thu, 20 Jun 2024 16:37:51 +0530 Subject: [PATCH 070/129] Add `MinDecimalValue()` function & `minTotalPledgeAmount` variable. --- core/part_token.go | 6 +++--- core/quorum_initiator.go | 7 ++++--- 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/core/part_token.go b/core/part_token.go index a90ec2e2..50c3f13e 100644 --- a/core/part_token.go +++ b/core/part_token.go @@ -18,15 +18,15 @@ func (c *Core) relaseToken(release *bool, token string) { c.w.ReleaseToken(token) } } - +func MinDecimalValue(num int) float64 { + return math.Pow(10, float64(-num)) +} func round(num float64) int { return int(num + math.Copysign(0.5, num)) } - func Ceilround(num float64) int { return int(math.Ceil(num)) } - func floatPrecision(num float64, precision int) float64 { precision = MaxDecimalPlaces output := math.Pow(10, float64(precision)) diff --git a/core/quorum_initiator.go b/core/quorum_initiator.go index 0985203d..71497523 100644 --- a/core/quorum_initiator.go +++ b/core/quorum_initiator.go @@ -313,9 +313,10 @@ func (c *Core) initiateConsensus(cr *ConensusRequest, sc *contract.Contract, dc case SmartContractExecuteMode: reqPledgeTokens = sc.GetTotalRBTs() } - //Minimum pledge value is 0.005 (ie, 0.005/5 = 0.001 per each quorum) - if reqPledgeTokens < 0.00005 { - reqPledgeTokens = 0.00005 + minValue := MinDecimalValue(MaxDecimalPlaces) + minTotalPledgeAmount := minValue * float64(MinQuorumRequired) + if reqPledgeTokens < minTotalPledgeAmount { + reqPledgeTokens = minTotalPledgeAmount } pd := PledgeDetails{ TransferAmount: reqPledgeTokens, From 19e19cec0c5e4fa1c01c7af37d8a7d77f883ba83 Mon Sep 17 00:00:00 2001 From: Vaishnav CH Date: Mon, 24 Jun 2024 11:58:40 +0530 Subject: [PATCH 071/129] Remove `MinTrnxAmt` constant --- core/core.go | 17 ++++++++--------- core/quorum_recv.go | 4 ++-- core/transfer.go | 2 +- 3 files changed, 11 insertions(+), 12 deletions(-) diff --git a/core/core.go b/core/core.go index 56c414d8..b5f0ac54 100644 --- a/core/core.go +++ b/core/core.go @@ -52,15 +52,14 @@ const ( ) const ( - InvalidPasringErr string = "invalid json parsing" - RubixRootDir string = "Rubix/" - DefaultMainNetDB string = "rubix.db" - DefaultTestNetDB string = "rubixtest.db" - MainNetDir string = "MainNet" - TestNetDir string = "TestNet" - TestNetDIDDir string = "TestNetDID/" - MinTrnxAmt float64 = 0.00001 - MaxDecimalPlaces int = 5 + InvalidPasringErr string = "invalid json parsing" + RubixRootDir string = "Rubix/" + DefaultMainNetDB string = "rubix.db" + DefaultTestNetDB string = "rubixtest.db" + MainNetDir string = "MainNet" + TestNetDir string = "TestNet" + TestNetDIDDir string = "TestNetDID/" + MaxDecimalPlaces int = 5 ) const ( diff --git a/core/quorum_recv.go b/core/quorum_recv.go index 26dc51f1..fb621dcb 100644 --- a/core/quorum_recv.go +++ b/core/quorum_recv.go @@ -578,8 +578,8 @@ func (c *Core) reqPledgeToken(req *ensweb.Request) *ensweb.Result { return c.l.RenderJSON(req, &crep, http.StatusOK) } - if (pr.TokensRequired) < MinTrnxAmt { - c.log.Error("Pledge amount is less than ", MinTrnxAmt) + if (pr.TokensRequired) < MinDecimalValue(MaxDecimalPlaces) { + c.log.Error("Pledge amount is less than ", MinDecimalValue(MaxDecimalPlaces)) crep.Message = "Pledge amount is less than minimum transcation amount" return c.l.RenderJSON(req, &crep, http.StatusOK) } diff --git a/core/transfer.go b/core/transfer.go index d4b2f516..c7ef3e20 100644 --- a/core/transfer.go +++ b/core/transfer.go @@ -51,7 +51,7 @@ func (c *Core) initiateRBTTransfer(reqID string, req *model.RBTTransferRequest) return resp } - if req.TokenCount < MinTrnxAmt { + if req.TokenCount < MinDecimalValue(MaxDecimalPlaces) { resp.Message = "Input transaction amount is less than minimum transaction amount" return resp } From 1f137492eb35c17c7f50432d894ee4fc96d0f3c3 Mon Sep 17 00:00:00 2001 From: Ashita Gupta Date: Mon, 24 Jun 2024 14:40:42 +0530 Subject: [PATCH 072/129] formatting --- server/tokens.go | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/server/tokens.go b/server/tokens.go index 516ee89c..b241d332 100644 --- a/server/tokens.go +++ b/server/tokens.go @@ -1,6 +1,7 @@ package server import ( + "fmt" "net/http" "github.com/rubixchain/rubixgoplatform/core/model" @@ -157,7 +158,7 @@ func (s *Server) APICheckPinnedState(req *ensweb.Request) *ensweb.Result { var br model.BasicResponse if len(provList) == 0 { br.Status = false - br.Message = "No pins available on " + tokenstatehash + br.Message = fmt.Sprintf("No pins available on %s", tokenstatehash) return s.RenderJSON(req, br, http.StatusOK) } else { br.Status = true From 3225bde22debd2dcb9367c8f563204eeda88f062 Mon Sep 17 00:00:00 2001 From: Ashita Gupta Date: Mon, 24 Jun 2024 14:47:02 +0530 Subject: [PATCH 073/129] test --- command/command.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/command/command.go b/command/command.go index bef52bad..884f25b6 100644 --- a/command/command.go +++ b/command/command.go @@ -33,7 +33,7 @@ const ( ) const ( - version string = "0.0.17" + version string = "0.0.17 copy branch" ) const ( VersionCmd string = "-v" From 2df83cca2a4188e359c122bc3a874be4e6df4ee8 Mon Sep 17 00:00:00 2001 From: KryptSai Date: Tue, 25 Jun 2024 11:06:55 +0530 Subject: [PATCH 074/129] smart contract folder renaming error --- core/smart_contract.go | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/core/smart_contract.go b/core/smart_contract.go index d803b969..39c77d63 100644 --- a/core/smart_contract.go +++ b/core/smart_contract.go @@ -344,6 +344,23 @@ func (c *Core) ContractCallBack(peerID string, topic string, data []byte) { c.log.Error("Fetch smart contract failed, failed to create smartcontract folder", "err", err) return } + // oldScFolder is set to path of the smartcontract folder + oldScFolder := c.cfg.DirPath + "SmartContract/" + fetchSC.SmartContractToken + var isPathExist bool + //info is set to FileInfo describing the oldScFolder + info, err := os.Stat(oldScFolder) + //If directory doesn't exist isPathExist is set to false + if os.IsNotExist(err) { + isPathExist = false + } else { + isPathExist = info.IsDir() + + } + //If isPathExist true, removing the existing folder which was generated while generating the smartcontract hash + if isPathExist { + c.log.Debug("removing the existing folder:", oldScFolder, "to add the new folder") + os.RemoveAll(oldScFolder) + } fetchSC.SmartContractTokenPath, err = c.RenameSCFolder(fetchSC.SmartContractTokenPath, fetchSC.SmartContractToken) if err != nil { c.log.Error("Fetch smart contract failed, failed to create SC folder", "err", err) From 9190dbbada68e6519a1287a799196116c91d894e Mon Sep 17 00:00:00 2001 From: Ashita Gupta Date: Fri, 28 Jun 2024 12:53:52 +0530 Subject: [PATCH 075/129] informing old quorums about exhausted state post transfer --- core/core.go | 1 + core/quorum_initiator.go | 50 ++++++++++++++++++++++++++++++++++++++-- core/quorum_recv.go | 19 +++++++++++---- core/wallet/token.go | 8 ++++--- 4 files changed, 69 insertions(+), 9 deletions(-) diff --git a/core/core.go b/core/core.go index 0a78001a..9b81d835 100644 --- a/core/core.go +++ b/core/core.go @@ -50,6 +50,7 @@ const ( APICheckQuorumStatusPath string = "/api/check-quorum-status" APIGetPeerDIDTypePath string = "/api/get-peer-didType" APIGetPeerInfoPath string = "/api/get-peer-info" + APIUpdateTokenHashDetails string = "/api/update-tokenhash-details" ) const ( diff --git a/core/quorum_initiator.go b/core/quorum_initiator.go index bc728543..eb1c9205 100644 --- a/core/quorum_initiator.go +++ b/core/quorum_initiator.go @@ -162,6 +162,7 @@ func (c *Core) QuroumSetup() { c.l.AddRoute(APISignatureRequest, "POST", c.signatureRequest) c.l.AddRoute(APISendReceiverToken, "POST", c.updateReceiverToken) c.l.AddRoute(APIUnlockTokens, "POST", c.unlockTokens) + c.l.AddRoute(APIUpdateTokenHashDetails, "POST", c.updateTokenHashDetails) if c.arbitaryMode { c.l.AddRoute(APIMapDIDArbitration, "POST", c.mapDIDArbitration) c.l.AddRoute(APICheckDIDArbitration, "GET", c.chekDIDArbitration) @@ -520,8 +521,8 @@ func (c *Core) initiateConsensus(cr *ConensusRequest, sc *contract.Contract, dc c.log.Error("Unable to send tokens to receiver", "msg", br.Message) return nil, nil, fmt.Errorf("unable to send tokens to receiver, " + br.Message) } - // br.Result will contain the new token state after sending tokens to receiver + // br.Result will contain the new token state after sending tokens to receiver as a response to APISendReceiverToken newtokenhashresult, ok := br.Result.([]interface{}) if !ok { fmt.Println("Type assertion to string failed") @@ -537,13 +538,40 @@ func (c *Core) initiateConsensus(cr *ConensusRequest, sc *contract.Contract, dc newtokenhashes = append(newtokenhashes, statehash) } - //trigger pledge finality to the quorum and also adding the tokenstate hash details to quorum + //trigger pledge finality to the quorum and also adding the new tokenstate hash details for transferred tokens to quorum pledgeFinalityError := c.quorumPledgeFinality(cr, nb, newtokenhashes) if pledgeFinalityError != nil { c.log.Error("Pledge finlaity not achieved", "err", err) return nil, nil, pledgeFinalityError } + //Checking prev block details (i.e. the latest block before transferring) by sender. Sender will connect with old quorums, and update about the exhausted token state hashes to quorums for them to unpledge their tokens. + for _, tokeninfo := range ti { + b := c.w.GetLatestTokenBlock(tokeninfo.Token, tokeninfo.TokenType) + signers, _ := b.GetSigner() + //if signer is similar to sender did skip this token, as the block is the genesys block + if signers[0] == sc.GetSenderDID() { + continue + } + //concat tokenId and BlockID + bid, _ := b.GetBlockID(tokeninfo.Token) + prevtokenIDTokenStateData := tokeninfo.Token + bid + prevtokenIDTokenStateBuffer := bytes.NewBuffer([]byte(prevtokenIDTokenStateData)) + + //add to ipfs get only the hash of the token+tokenstate. This is the hash just before transferring i.e. the exhausted token state hash, and updating in Sender side + prevtokenIDTokenStateHash, _ := c.ipfs.Add(prevtokenIDTokenStateBuffer, ipfsnode.Pin(false), ipfsnode.OnlyHash(true)) + + //send this exhausted hash to old quorums to unpledge + for _, signer := range signers { + signer_peeerId := c.w.GetPeerID(signer) + signer_addr := signer_peeerId + "." + signer + p, _ := c.getPeer(signer_addr, "") + m := make(map[string]string) + m["tokenIDTokenStateHash"] = prevtokenIDTokenStateHash + _ = p.SendJSONRequest("POST", APIUpdateTokenHashDetails, m, nil, nil, true) + } + } + err = c.w.TokensTransferred(sc.GetSenderDID(), ti, nb, rp.IsLocal()) if err != nil { c.log.Error("Failed to transfer tokens", "err", err) @@ -670,6 +698,10 @@ func (c *Core) initiateConsensus(cr *ConensusRequest, sc *contract.Contract, dc return &txnDetails, pl, nil } else { //execute mode + //Get the latest block details before being executed to get the old signers + b := c.w.GetLatestTokenBlock(cr.SmartContractToken, nb.GetTokenType(cr.SmartContractToken)) + signers, _ := b.GetSigner() + //Create tokechain for the smart contract token and add genesys block err = c.w.AddTokenBlock(cr.SmartContractToken, nb) if err != nil { @@ -715,6 +747,20 @@ func (c *Core) initiateConsensus(cr *ConensusRequest, sc *contract.Contract, dc c.log.Error("Failed to publish smart contract Executed info") } + //inform old quorums about exhausted smart contract token hash + prevBlockId, _ := nb.GetPrevBlockID((cr.SmartContractToken)) + scTokenStateDataOld := cr.SmartContractToken + prevBlockId + scTokenStateDataOldBuffer := bytes.NewBuffer([]byte(scTokenStateDataOld)) + oldsctokenIDTokenStateHash, _ := c.ipfs.Add(scTokenStateDataOldBuffer, ipfsnode.Pin(false), ipfsnode.OnlyHash(true)) + for _, signer := range signers { + signer_peeerId := c.w.GetPeerID(signer) + signer_addr := signer_peeerId + "." + signer + p, _ := c.getPeer(signer_addr, "") + m := make(map[string]string) + m["tokenIDTokenStateHash"] = oldsctokenIDTokenStateHash + _ = p.SendJSONRequest("POST", APIUpdateTokenHashDetails, m, nil, nil, true) + } + txnDetails := wallet.TransactionDetails{ TransactionID: tid, TransactionType: nb.GetTransType(), diff --git a/core/quorum_recv.go b/core/quorum_recv.go index e8aae966..d45c47ca 100644 --- a/core/quorum_recv.go +++ b/core/quorum_recv.go @@ -806,12 +806,10 @@ func (c *Core) updateReceiverToken(req *ensweb.Request) *ensweb.Result { c.w.AddTransactionHistory(td) crep.Status = true crep.Message = "Token received successfully" - //Adding quorums to DIDPeerTable of receiver for _, qrm := range sr.QuorumInfo { c.w.AddDIDPeerMap(qrm.DID, qrm.PeerID, *qrm.DIDType) } - crep.Result = updatedtokenhashes return c.l.RenderJSON(req, &crep, http.StatusOK) } @@ -1029,8 +1027,8 @@ func (c *Core) mapDIDArbitration(req *ensweb.Request) *ensweb.Result { } err = c.srv.UpdateTokenDetials(nd) if err != nil { - c.log.Error("Failed to update table detials", "err", err) - br.Message = "Failed to update token detials" + c.log.Error("Failed to update table details", "err", err) + br.Message = "Failed to update token details" return c.l.RenderJSON(req, &br, http.StatusOK) } dm := &service.DIDMap{ @@ -1375,3 +1373,16 @@ func (c *Core) unlockTokens(req *ensweb.Request) *ensweb.Result { return c.l.RenderJSON(req, &crep, http.StatusOK) } + +func (c *Core) updateTokenHashDetails(req *ensweb.Request) *ensweb.Result { + c.log.Debug("Updating tokenStateHashDetails in DB") + tokenIDTokenStateHash := c.l.GetQuerry(req, "tokenIDTokenStateHash") + c.log.Debug("tokenIDTokenStateHash from query", tokenIDTokenStateHash) + + err := c.w.RemoveTokenStateHash(tokenIDTokenStateHash) + if err == nil { + fmt.Println("removed hash successfully") + } + return c.l.RenderJSON(req, nil, http.StatusOK) + +} diff --git a/core/wallet/token.go b/core/wallet/token.go index 711afd31..189d43ff 100644 --- a/core/wallet/token.go +++ b/core/wallet/token.go @@ -667,9 +667,12 @@ func (w *Wallet) RemoveTokenStateHash(tokenstatehash string) error { pledgedTokensList := strings.Split(td.PledgedTokens, " ") - for _, v := range pledgedTokensList { + for _, pledgedToken := range pledgedTokensList { + if strings.TrimSpace(pledgedToken) == "" { + continue + } var tokend Token - err = w.s.Read(TokenStorage, &tokend, "did=? AND token_id=?", td.DID, v) + err = w.s.Read(TokenStorage, &tokend, "did=? AND token_id=?", td.DID, pledgedToken) if err != nil { w.log.Error("Failed to read token details from DB", "err", err) return err @@ -687,6 +690,5 @@ func (w *Wallet) RemoveTokenStateHash(tokenstatehash string) error { w.log.Error("Failed to delete token state from DB", "err", err) return err } - fmt.Println("Delete TokenStateDetails : ", td1) return nil } From 5d115f8ac670914cf6fc7b9d8f2f590111e79a1f Mon Sep 17 00:00:00 2001 From: KryptSai Date: Fri, 28 Jun 2024 17:28:30 +0530 Subject: [PATCH 076/129] resolving re-creation of smartcontract token --- core/smart_contract.go | 5 ++++- core/wallet/smart_contract.go | 12 +++++++++--- 2 files changed, 13 insertions(+), 4 deletions(-) diff --git a/core/smart_contract.go b/core/smart_contract.go index 39c77d63..b60cd634 100644 --- a/core/smart_contract.go +++ b/core/smart_contract.go @@ -349,7 +349,7 @@ func (c *Core) ContractCallBack(peerID string, topic string, data []byte) { var isPathExist bool //info is set to FileInfo describing the oldScFolder info, err := os.Stat(oldScFolder) - //If directory doesn't exist isPathExist is set to false + //If directory doesn't exist, isPathExist is set to false if os.IsNotExist(err) { isPathExist = false } else { @@ -368,10 +368,13 @@ func (c *Core) ContractCallBack(peerID string, topic string, data []byte) { } c.FetchSmartContract(requestID, &fetchSC) c.log.Info("Smart contract " + fetchSC.SmartContractToken + " files fetching succesful") + c.log.Debug("SmartContractTokenPath", fetchSC.SmartContractTokenPath) } smartContractToken := newEvent.SmartContractToken scFolderPath := c.cfg.DirPath + "SmartContract/" + smartContractToken + c.log.Debug("scfolderpath", scFolderPath) if _, err := os.Stat(scFolderPath); os.IsNotExist(err) { + c.log.Debug("sc folder path does not exist") fetchSC.SmartContractToken = smartContractToken fetchSC.SmartContractTokenPath, err = c.CreateSCTempFolder() if err != nil { diff --git a/core/wallet/smart_contract.go b/core/wallet/smart_contract.go index 1a1fbe1d..19830d76 100644 --- a/core/wallet/smart_contract.go +++ b/core/wallet/smart_contract.go @@ -21,10 +21,16 @@ type CallBackUrl struct { } func (w *Wallet) CreateSmartContractToken(sc *SmartContract) error { - err := w.s.Write(SmartContractStorage, sc) + var sc_info SmartContract + //to check whether smart contract hash already exist in the DB, and write if it doesn't exist + err := w.s.Read(SmartContractStorage, &sc_info, "smart_contract_hash=?", sc.SmartContractHash) if err != nil { - w.log.Error("Failed to write smart contract token", "err", err) - return err + err := w.s.Write(SmartContractStorage, sc) + if err != nil { + w.log.Error("Failed to write smart contract token", "err", err) + return err + } + return nil } return nil } From c8cb7c3bf0b6c1a091bcc4fd3c04f9c7e707897e Mon Sep 17 00:00:00 2001 From: Ashita Gupta Date: Mon, 1 Jul 2024 13:43:12 +0530 Subject: [PATCH 077/129] Updating swagger and readme --- README.md | 25 ++++++++++++++ client/token.go | 2 +- docs/docs.go | 84 +++++++++++++++++++++++++++++++++++++++++++++++ docs/swagger.json | 84 +++++++++++++++++++++++++++++++++++++++++++++++ docs/swagger.yaml | 57 ++++++++++++++++++++++++++++++++ server/server.go | 2 +- server/tokens.go | 16 +++++++++ 7 files changed, 268 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 34ca4965..6aa65b90 100644 --- a/README.md +++ b/README.md @@ -367,4 +367,29 @@ This following options are used for this command -didType int DID type (0-Basic Mode, 1-Standard Mode, 2-Wallet Mode, 3-Child Mode, 4-Light Mode) (default 0) +``` + +To check details about the token states for which pledging has been done +: To check for what token states the pledging has been done, and which tokens are pledged + +``` +./rubixgoplatform getpledgedtokendetails + +This following options are used for this command + -port string + Server/Host port (default "20000") +``` + +To check tokenstatehash status +: To check if a particular tokenstatehash is exhausted, i.e if it has been transferred further + +``` +./rubixgoplatform tokenstatehash + +This following options are used for this command + -port string + Server/Host port (default "20000") + + -tokenstatehash string + TokenState Hash, for which the status needs to be checked ``` \ No newline at end of file diff --git a/client/token.go b/client/token.go index 0bbd9668..0c6a4b29 100644 --- a/client/token.go +++ b/client/token.go @@ -46,7 +46,7 @@ func (c *Client) GetPinnedInfo(TokenStateHash string) (*model.BasicResponse, err m := make(map[string]string) m["tokenstatehash"] = TokenStateHash var br model.BasicResponse - err := c.sendJSONRequest("GET", setup.APICheckPinnedState, m, nil, &br, time.Minute*2) + err := c.sendJSONRequest("DELETE", setup.APICheckPinnedState, m, nil, &br, time.Minute*2) if err != nil { c.log.Error("Failed to get Pins", "err", err) return nil, err diff --git a/docs/docs.go b/docs/docs.go index 973f307b..1387e788 100644 --- a/docs/docs.go +++ b/docs/docs.go @@ -86,6 +86,38 @@ const docTemplate = `{ } } }, + "/api/check-pinned-state": { + "delete": { + "description": "This API is used to check if the token state for which the token is pledged is exhausted or not.", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "Account" + ], + "summary": "Check for exhausted token state hash", + "parameters": [ + { + "type": "string", + "description": "Token State Hash", + "name": "tokenstatehash", + "in": "query", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/model.BasicResponse" + } + } + } + } + }, "/api/commit-data-token": { "post": { "description": "This API will create data token", @@ -590,6 +622,26 @@ const docTemplate = `{ } } }, + "/api/get-pledgedtoken-details": { + "get": { + "description": "This API allows the user to get details about the tokens the quorums have pledged i.e. which token is pledged for which token state", + "produces": [ + "application/json" + ], + "tags": [ + "Account" + ], + "summary": "Get details about the pledged tokens", + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/model.TokenStateResponse" + } + } + } + } + }, "/api/get-smart-contract-token-chain-data": { "post": { "description": "This API will return smart contract token chain data", @@ -881,6 +933,38 @@ const docTemplate = `{ } } }, + "model.PledgedTokenStateDetails": { + "type": "object", + "properties": { + "did": { + "type": "string" + }, + "token": { + "type": "string" + }, + "token_state": { + "type": "string" + } + } + }, + "model.TokenStateResponse": { + "type": "object", + "properties": { + "message": { + "type": "string" + }, + "result": {}, + "status": { + "type": "boolean" + }, + "token_state_details": { + "type": "array", + "items": { + "$ref": "#/definitions/model.PledgedTokenStateDetails" + } + } + } + }, "model.TxnCountForDID": { "type": "object", "properties": { diff --git a/docs/swagger.json b/docs/swagger.json index 95143433..e3630c1f 100644 --- a/docs/swagger.json +++ b/docs/swagger.json @@ -78,6 +78,38 @@ } } }, + "/api/check-pinned-state": { + "delete": { + "description": "This API is used to check if the token state for which the token is pledged is exhausted or not.", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "Account" + ], + "summary": "Check for exhausted token state hash", + "parameters": [ + { + "type": "string", + "description": "Token State Hash", + "name": "tokenstatehash", + "in": "query", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/model.BasicResponse" + } + } + } + } + }, "/api/commit-data-token": { "post": { "description": "This API will create data token", @@ -582,6 +614,26 @@ } } }, + "/api/get-pledgedtoken-details": { + "get": { + "description": "This API allows the user to get details about the tokens the quorums have pledged i.e. which token is pledged for which token state", + "produces": [ + "application/json" + ], + "tags": [ + "Account" + ], + "summary": "Get details about the pledged tokens", + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/model.TokenStateResponse" + } + } + } + } + }, "/api/get-smart-contract-token-chain-data": { "post": { "description": "This API will return smart contract token chain data", @@ -873,6 +925,38 @@ } } }, + "model.PledgedTokenStateDetails": { + "type": "object", + "properties": { + "did": { + "type": "string" + }, + "token": { + "type": "string" + }, + "token_state": { + "type": "string" + } + } + }, + "model.TokenStateResponse": { + "type": "object", + "properties": { + "message": { + "type": "string" + }, + "result": {}, + "status": { + "type": "boolean" + }, + "token_state_details": { + "type": "array", + "items": { + "$ref": "#/definitions/model.PledgedTokenStateDetails" + } + } + } + }, "model.TxnCountForDID": { "type": "object", "properties": { diff --git a/docs/swagger.yaml b/docs/swagger.yaml index 17ba1455..3ef35f4e 100644 --- a/docs/swagger.yaml +++ b/docs/swagger.yaml @@ -44,6 +44,27 @@ definitions: $ref: '#/definitions/model.NFTStatus' type: array type: object + model.PledgedTokenStateDetails: + properties: + did: + type: string + token: + type: string + token_state: + type: string + type: object + model.TokenStateResponse: + properties: + message: + type: string + result: {} + status: + type: boolean + token_state_details: + items: + $ref: '#/definitions/model.PledgedTokenStateDetails' + type: array + type: object model.TxnCountForDID: properties: message: @@ -198,6 +219,28 @@ paths: summary: Add NFTs tags: - NFT + /api/check-pinned-state: + delete: + consumes: + - application/json + description: This API is used to check if the token state for which the token + is pledged is exhausted or not. + parameters: + - description: Token State Hash + in: query + name: tokenstatehash + required: true + type: string + produces: + - application/json + responses: + "200": + description: OK + schema: + $ref: '#/definitions/model.BasicResponse' + summary: Check for exhausted token state hash + tags: + - Account /api/commit-data-token: post: consumes: @@ -531,6 +574,20 @@ paths: summary: Get Data Token tags: - Data Tokens + /api/get-pledgedtoken-details: + get: + description: This API allows the user to get details about the tokens the quorums + have pledged i.e. which token is pledged for which token state + produces: + - application/json + responses: + "200": + description: OK + schema: + $ref: '#/definitions/model.TokenStateResponse' + summary: Get details about the pledged tokens + tags: + - Account /api/get-smart-contract-token-chain-data: post: consumes: diff --git a/server/server.go b/server/server.go index 2196a48e..57ac8fab 100644 --- a/server/server.go +++ b/server/server.go @@ -162,7 +162,7 @@ func (s *Server) RegisterRoutes() { s.AddRoute(setup.APIRemoveExplorer, "POST", s.AuthHandle(s.APIRemoveExplorer, false, s.AuthError, true)) s.AddRoute(setup.APIAddPeerDetails, "POST", s.AuthHandle(s.APIAddPeerDetails, false, s.AuthError, true)) s.AddRoute(setup.APIGetPledgedTokenDetails, "GET", s.AuthHandle(s.APIGetPledgedTokenDetails, false, s.AuthError, true)) - s.AddRoute(setup.APICheckPinnedState, "GET", s.AuthHandle(s.APICheckPinnedState, false, s.AuthError, true)) + s.AddRoute(setup.APICheckPinnedState, "DELETE", s.AuthHandle(s.APICheckPinnedState, false, s.AuthError, true)) } func (s *Server) ExitFunc() error { diff --git a/server/tokens.go b/server/tokens.go index b241d332..8c278152 100644 --- a/server/tokens.go +++ b/server/tokens.go @@ -132,6 +132,13 @@ func (s *Server) APISignatureResponse(req *ensweb.Request) *ensweb.Result { return s.didResponse(req, resp.ID) } +// APIGetPledgedTokenDetails godoc +// @Summary Get details about the pledged tokens +// @Description This API allows the user to get details about the tokens the quorums have pledged i.e. which token is pledged for which token state +// @Tags Account +// @Produce json +// @Success 200 {object} model.TokenStateResponse +// @Router /api/get-pledgedtoken-details [get] func (s *Server) APIGetPledgedTokenDetails(req *ensweb.Request) *ensweb.Result { pledgedTokenInfo, err := s.c.GetPledgedInfo() if err != nil { @@ -148,6 +155,15 @@ func (s *Server) APIGetPledgedTokenDetails(req *ensweb.Request) *ensweb.Result { return s.RenderJSON(req, tokenstateresponse, http.StatusOK) } +// APICheckPinnedState godoc +// @Summary Check for exhausted token state hash +// @Description This API is used to check if the token state for which the token is pledged is exhausted or not. +// @Tags Account +// @Accept json +// @Produce json +// @Param tokenstatehash query string true "Token State Hash" +// @Success 200 {object} model.BasicResponse +// @Router /api/check-pinned-state [delete] func (s *Server) APICheckPinnedState(req *ensweb.Request) *ensweb.Result { tokenstatehash := s.GetQuerry(req, "tokenstatehash") From 63866b5584403e13cbf42f2d15ce454ef71085c4 Mon Sep 17 00:00:00 2001 From: Ashita Gupta <38140293+ashi31@users.noreply.github.com> Date: Mon, 1 Jul 2024 13:55:46 +0530 Subject: [PATCH 078/129] Update command.go --- command/command.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/command/command.go b/command/command.go index 36fd44e3..e24c0d73 100644 --- a/command/command.go +++ b/command/command.go @@ -33,7 +33,7 @@ const ( ) const ( - version string = "0.0.17 copy branch" + version string = "0.0.17" ) const ( VersionCmd string = "-v" From 3af856a691e6587e370e88432f638fb05de1392d Mon Sep 17 00:00:00 2001 From: Ashita Gupta Date: Thu, 4 Jul 2024 01:48:55 +0530 Subject: [PATCH 079/129] minor edits --- command/tokenstate.go | 2 +- core/wallet/token.go | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/command/tokenstate.go b/command/tokenstate.go index 4dd26906..d56a3e0b 100644 --- a/command/tokenstate.go +++ b/command/tokenstate.go @@ -30,7 +30,7 @@ func (cmd *Command) CheckPinnedState() { } fmt.Printf("Response : %v\n", info) if !info.Status { - cmd.log.Error("Pin not available", "message", info.Message) + cmd.log.Debug("Pin not available", "message", info.Message) } else { cmd.log.Info("Token State is Pinned") } diff --git a/core/wallet/token.go b/core/wallet/token.go index 189d43ff..3a2a5bd9 100644 --- a/core/wallet/token.go +++ b/core/wallet/token.go @@ -605,7 +605,7 @@ func (w *Wallet) AddTokenStateHash(did string, tokenstatehashes []string, pledge concatenatedpledgedtokens := "" for _, i := range pledgedtokens { - concatenatedpledgedtokens = concatenatedpledgedtokens + i + " " + concatenatedpledgedtokens = concatenatedpledgedtokens + i + "," } for _, tokenstatehash := range tokenstatehashes { @@ -665,7 +665,7 @@ func (w *Wallet) RemoveTokenStateHash(tokenstatehash string) error { return nil } - pledgedTokensList := strings.Split(td.PledgedTokens, " ") + pledgedTokensList := strings.Split(td.PledgedTokens, ",") for _, pledgedToken := range pledgedTokensList { if strings.TrimSpace(pledgedToken) == "" { From 23bf9696addeb6192b8ece459bab496915a16e7f Mon Sep 17 00:00:00 2001 From: Ashita Gupta Date: Thu, 4 Jul 2024 12:39:06 +0530 Subject: [PATCH 080/129] code update --- core/wallet/token.go | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/core/wallet/token.go b/core/wallet/token.go index 3a2a5bd9..dcafbcd4 100644 --- a/core/wallet/token.go +++ b/core/wallet/token.go @@ -602,11 +602,7 @@ func (w *Wallet) AddTokenStateHash(did string, tokenstatehashes []string, pledge if tokenstatehashes == nil { return nil } - concatenatedpledgedtokens := "" - - for _, i := range pledgedtokens { - concatenatedpledgedtokens = concatenatedpledgedtokens + i + "," - } + concatenatedpledgedtokens := strings.Join(pledgedtokens, ",") for _, tokenstatehash := range tokenstatehashes { td.DID = did From af9ccf4f7ceabaf0c96f48f52ab6076dc50b87a6 Mon Sep 17 00:00:00 2001 From: Ashita Gupta Date: Thu, 4 Jul 2024 19:35:07 +0530 Subject: [PATCH 081/129] adding token state hash with the receiver --- core/quorum_recv.go | 33 +++++++++++++++++++++------------ core/wallet/token.go | 26 ++++++++++++++++++++------ 2 files changed, 41 insertions(+), 18 deletions(-) diff --git a/core/quorum_recv.go b/core/quorum_recv.go index d45c47ca..392e6b5e 100644 --- a/core/quorum_recv.go +++ b/core/quorum_recv.go @@ -761,27 +761,18 @@ func (c *Core) updateReceiverToken(req *ensweb.Request) *ensweb.Result { c.log.Debug("Token", tokenStateCheckResult[i].Token, "Message", tokenStateCheckResult[i].Message) } senderPeerId, _, _ := util.ParseAddress(sr.Address) + err = c.w.TokensReceived(did, sr.TokenInfo, b, senderPeerId, c.peerID) if err != nil { c.log.Error("Failed to update token status", "err", err) crep.Message = "Failed to update token status" return c.l.RenderJSON(req, &crep, http.StatusOK) } - sc := contract.InitContract(b.GetSmartContract(), nil) - if sc == nil { - c.log.Error("Failed to update token status, missing smart contract") - crep.Message = "Failed to update token status, missing smart contract" - return c.l.RenderJSON(req, &crep, http.StatusOK) - } - bid, err := b.GetBlockID(sr.TokenInfo[0].Token) - if err != nil { - c.log.Error("Failed to update token status, failed to get block ID", "err", err) - crep.Message = "Failed to update token status, failed to get block ID" - return c.l.RenderJSON(req, &crep, http.StatusOK) - } + //add to ipfs to get latest Token State Hash after receiving the token by receiver. The hashes will be returned to sender, and from there to //quorums using pledgefinality function, to be added to TokenStateHash Table var updatedtokenhashes []string + var tokenwithtokenhash []string for _, ti := range sr.TokenInfo { t := ti.Token b := c.w.GetLatestTokenBlock(ti.Token, ti.TokenType) @@ -790,7 +781,25 @@ func (c *Core) updateReceiverToken(req *ensweb.Request) *ensweb.Result { tokenIDTokenStateBuffer := bytes.NewBuffer([]byte(tokenIDTokenStateData)) tokenIDTokenStateHash, _ := c.ipfs.Add(tokenIDTokenStateBuffer, ipfsnode.Pin(false), ipfsnode.OnlyHash(true)) updatedtokenhashes = append(updatedtokenhashes, tokenIDTokenStateHash) + tokenwithtokenhash = append(tokenwithtokenhash, t+"."+tokenIDTokenStateHash) } + + //Updating the latest tokenstatehash with the new owner i.e. receiver + c.w.TokenStateHashUpdate(tokenwithtokenhash) + + sc := contract.InitContract(b.GetSmartContract(), nil) + if sc == nil { + c.log.Error("Failed to update token status, missing smart contract") + crep.Message = "Failed to update token status, missing smart contract" + return c.l.RenderJSON(req, &crep, http.StatusOK) + } + bid, err := b.GetBlockID(sr.TokenInfo[0].Token) + if err != nil { + c.log.Error("Failed to update token status, failed to get block ID", "err", err) + crep.Message = "Failed to update token status, failed to get block ID" + return c.l.RenderJSON(req, &crep, http.StatusOK) + } + td := &wallet.TransactionDetails{ TransactionID: b.GetTid(), TransactionType: b.GetTransType(), diff --git a/core/wallet/token.go b/core/wallet/token.go index dcafbcd4..fbd6c8de 100644 --- a/core/wallet/token.go +++ b/core/wallet/token.go @@ -38,11 +38,12 @@ const ( ) type Token struct { - TokenID string `gorm:"column:token_id;primaryKey"` - ParentTokenID string `gorm:"column:parent_token_id"` - TokenValue float64 `gorm:"column:token_value"` - DID string `gorm:"column:did"` - TokenStatus int `gorm:"column:token_status;"` + TokenID string `gorm:"column:token_id;primaryKey"` + ParentTokenID string `gorm:"column:parent_token_id"` + TokenValue float64 `gorm:"column:token_value"` + DID string `gorm:"column:did"` + TokenStatus int `gorm:"column:token_status;"` + TokenStateHash string `gorm:"column:token_state_hash"` } func (w *Wallet) CreateToken(t *Token) error { @@ -416,7 +417,6 @@ func (w *Wallet) TokensReceived(did string, ti []contract.TokenInfo, b *block.Bl return err } } - t.DID = did t.TokenStatus = TokenIsFree err = w.s.Update(TokenStorage, &t, "token_id=?", ti[i].Token) @@ -454,6 +454,20 @@ func (w *Wallet) TokensReceived(did string, ti []contract.TokenInfo, b *block.Bl return nil } +func (w *Wallet) TokenStateHashUpdate(tokenwithtokenhash []string) { + w.l.Lock() + defer w.l.Unlock() + var t Token + for _, val := range tokenwithtokenhash { + token := strings.Split(val, ".")[0] + tokenstatehash := strings.Split(val, ".")[1] + _ = w.s.Read(TokenStorage, &t, "token_id=?", token) + t.TokenStateHash = tokenstatehash + _ = w.s.Update(TokenStorage, &t, "token_id=?", token) + } + +} + func (w *Wallet) CommitTokens(did string, rbtTokens []string) error { w.l.Lock() defer w.l.Unlock() From 130c3ba245fe4a5719d2ff7a2ea1ae7a5a509ead Mon Sep 17 00:00:00 2001 From: Ashita Gupta Date: Mon, 8 Jul 2024 01:59:52 +0530 Subject: [PATCH 082/129] client side parameter validation checks --- command/bootstrap.go | 4 +-- command/data_token.go | 9 +++++ command/diagnostic.go | 10 ++++++ command/did.go | 17 +++++++++ command/migrate.go | 4 +++ command/ping.go | 18 ++++++++++ command/quorurm.go | 15 ++++++++ command/smartContract.go | 75 ++++++++++++++++++++++++++++++++++++++++ command/token.go | 10 ++++++ command/transfer.go | 37 ++++++++++++++++++++ command/txndetails.go | 13 ++++++- 11 files changed, 209 insertions(+), 3 deletions(-) diff --git a/command/bootstrap.go b/command/bootstrap.go index b0bc6364..666789a0 100644 --- a/command/bootstrap.go +++ b/command/bootstrap.go @@ -2,7 +2,7 @@ package command func (cmd *Command) addBootStrap() { if len(cmd.peers) == 0 { - cmd.log.Error("Peers required for bootstrap") + cmd.log.Error("Peers required for bootstrap. Use flag -peers to provide peers separated by a ','") return } msg, status := cmd.c.AddBootStrap(cmd.peers) @@ -16,7 +16,7 @@ func (cmd *Command) addBootStrap() { func (cmd *Command) removeBootStrap() { if len(cmd.peers) == 0 { - cmd.log.Error("Peers required for bootstrap") + cmd.log.Error("Peers required for bootstrap. Use flag -peers to provide peers separated by a ','") return } msg, status := cmd.c.RemoveBootStrap(cmd.peers) diff --git a/command/data_token.go b/command/data_token.go index a42fdad7..7d442c09 100644 --- a/command/data_token.go +++ b/command/data_token.go @@ -5,6 +5,7 @@ import ( "fmt" "io/ioutil" "path" + "strings" "github.com/rubixchain/rubixgoplatform/client" "github.com/rubixchain/rubixgoplatform/core" @@ -12,6 +13,10 @@ import ( ) func (cmd *Command) createDataToken() { + if !strings.HasPrefix(cmd.did, "bafybmi") || len(cmd.did) < 59 { + cmd.log.Error("Invalid DID") + return + } dt := client.DataTokenReq{ DID: cmd.did, UserID: cmd.userID, @@ -59,6 +64,10 @@ func (cmd *Command) createDataToken() { } func (cmd *Command) commitDataToken() { + if !strings.HasPrefix(cmd.did, "bafybmi") || len(cmd.did) < 59 { + cmd.log.Error("Invalid DID") + return + } br, err := cmd.c.CommitDataToken(cmd.did, cmd.batchID) if err != nil { cmd.log.Error("Failed to commit data token", "err", err) diff --git a/command/diagnostic.go b/command/diagnostic.go index 4b3fe59d..e9c3f287 100644 --- a/command/diagnostic.go +++ b/command/diagnostic.go @@ -3,6 +3,7 @@ package command import ( "fmt" "os" + "strings" "github.com/rubixchain/rubixgoplatform/block" "github.com/rubixchain/rubixgoplatform/util" @@ -133,6 +134,11 @@ func tcMarshal(str string, m interface{}) (string, error) { } func (cmd *Command) dumpTokenChain() { + if len(cmd.token) < 46 || !strings.HasPrefix(cmd.token, "Qm") { + cmd.log.Error("Invalid smart contract token") + return + } + blocks := make([]map[string]interface{}, 0) blockID := "" for { @@ -174,6 +180,10 @@ func (cmd *Command) dumpTokenChain() { } func (cmd *Command) dumpSmartContractTokenChain() { + if len(cmd.smartContractToken) < 46 || !strings.HasPrefix(cmd.smartContractToken, "Qm") { + cmd.log.Error("Invalid smart contract token") + return + } blocks := make([]map[string]interface{}, 0) blockID := "" for { diff --git a/command/did.go b/command/did.go index 00cb9229..30c72cff 100644 --- a/command/did.go +++ b/command/did.go @@ -6,6 +6,7 @@ import ( "image" "io/ioutil" "os" + "strings" "time" "github.com/rubixchain/rubixgoplatform/core/model" @@ -50,6 +51,10 @@ func (cmd *Command) CreateDID() { } cmd.quorumPWD = pwd } + if cmd.didType < 0 || cmd.didType > 4 { + cmd.log.Error("DID Type should be between 0 and 4") + return + } if cmd.didType == did.LiteDIDMode { if cmd.privKeyFile == "" || cmd.pubKeyFile == "" { cmd.log.Error("private key & public key file names required") @@ -180,6 +185,10 @@ func (cmd *Command) GetAllDID() { } func (cmd *Command) RegsiterDIDCmd() { + if !strings.HasPrefix(cmd.did, "bafybmi") || len(cmd.did) < 59 { + cmd.log.Error("Invalid DID") + return + } br, err := cmd.c.RegisterDID(cmd.did) if err != nil { @@ -202,6 +211,10 @@ func (cmd *Command) RegsiterDIDCmd() { } func (cmd *Command) SetupDIDCmd() { + if !strings.HasPrefix(cmd.did, "bafybmi") || len(cmd.did) < 59 { + cmd.log.Error("Invalid DID") + return + } br, err := cmd.c.RegisterDID(cmd.did) if err != nil { @@ -322,6 +335,10 @@ func (cmd *Command) SignatureResponse(br *model.BasicResponse, timeout ...time.D } func (cmd *Command) GetAccountInfo() { + if !strings.HasPrefix(cmd.did, "bafybmi") || len(cmd.did) < 59 { + cmd.log.Error("Invalid DID") + return + } info, err := cmd.c.GetAccountInfo(cmd.did) if err != nil { cmd.log.Error("Invalid response from the node", "err", err) diff --git a/command/migrate.go b/command/migrate.go index d3f7f5f4..d36ace7e 100644 --- a/command/migrate.go +++ b/command/migrate.go @@ -42,6 +42,10 @@ func (cmd *Command) MigrateNodeCmd() { } cmd.quorumPWD = pwd } + if cmd.didType < 0 || cmd.didType > 4 { + cmd.log.Error("DID Type should be between 0 and 4") + return + } r := core.MigrateRequest{ DIDType: cmd.didType, PrivPWD: cmd.privPWD, diff --git a/command/ping.go b/command/ping.go index 5623ec62..f00b115f 100644 --- a/command/ping.go +++ b/command/ping.go @@ -1,10 +1,19 @@ package command import ( + "fmt" "strings" ) func (cmd *Command) ping() { + if cmd.peerID == "" { + cmd.log.Error("PeerID cannot be empty. Please use flag peerId") + return + } + if !strings.HasPrefix(cmd.peerID, "12D3KooW") || len(cmd.peerID) < 52 { + cmd.log.Error("Invalid PeerID") + return + } msg, status := cmd.c.Ping(cmd.peerID) if !status { cmd.log.Error("Ping failed", "message", msg) @@ -14,6 +23,15 @@ func (cmd *Command) ping() { } func (cmd *Command) checkQuorumStatus() { + if cmd.quorumAddr == "" { + cmd.log.Info("Quorum Address cannot be empty") + fmt.Print("Enter Quorum Address : ") + _, err := fmt.Scan(&cmd.quorumAddr) + if err != nil { + cmd.log.Error("Failed to get Quorum Address") + return + } + } msg, _ := cmd.c.CheckQuorumStatus(cmd.quorumAddr) //Verification with "status" pending ! if strings.Contains(msg, "Quorum is setup") { diff --git a/command/quorurm.go b/command/quorurm.go index 8f864b0d..7060908e 100644 --- a/command/quorurm.go +++ b/command/quorurm.go @@ -2,6 +2,7 @@ package command import ( "fmt" + "strings" ) func (cmd *Command) AddQuorurm() { @@ -47,6 +48,20 @@ func (cmd *Command) SetupQuorum() { } cmd.quorumPWD = pwd } + + if cmd.did == "" { + cmd.log.Info("Quorum DID cannot be empty") + fmt.Print("Enter Quorum DID : ") + _, err := fmt.Scan(&cmd.did) + if err != nil { + cmd.log.Error("Failed to get Quorum DID") + return + } + } + if !strings.HasPrefix(cmd.did, "bafybmi") || len(cmd.did) < 59 { + cmd.log.Error("Invalid DID") + return + } msg, status := cmd.c.SetupQuorum(cmd.did, cmd.quorumPWD, cmd.privPWD) if !status { diff --git a/command/smartContract.go b/command/smartContract.go index 30f4f7a2..4acc52c9 100644 --- a/command/smartContract.go +++ b/command/smartContract.go @@ -1,12 +1,31 @@ package command import ( + "fmt" + "strings" + "github.com/rubixchain/rubixgoplatform/client" "github.com/rubixchain/rubixgoplatform/core" "github.com/rubixchain/rubixgoplatform/core/model" ) func (cmd *Command) generateSmartContractToken() { + if !strings.HasPrefix(cmd.did, "bafybmi") || len(cmd.did) < 59 { + cmd.log.Error("Invalid DID") + return + } + if cmd.binaryCodePath == "" { + cmd.log.Error("Please provide Binary code file") + return + } + if cmd.rawCodePath == "" { + cmd.log.Error("Please provide Raw code file") + return + } + if cmd.schemaFilePath == "" { + cmd.log.Error("Please provide Schema file") + return + } smartContractTokenRequest := core.GenerateSmartContractRequest{ BinaryCode: cmd.binaryCodePath, RawCode: cmd.rawCodePath, @@ -35,6 +54,10 @@ func (cmd *Command) generateSmartContractToken() { } func (cmd *Command) fetchSmartContract() { + if len(cmd.smartContractToken) < 46 || !strings.HasPrefix(cmd.smartContractToken, "Qm") { + cmd.log.Error("Invalid smart contract token") + return + } smartContractTokenRequest := core.FetchSmartContractRequest{ SmartContractToken: cmd.smartContractToken, } @@ -55,6 +78,18 @@ func (cmd *Command) fetchSmartContract() { cmd.log.Info("Smart contract token fetched successfully") } func (cmd *Command) PublishContract() { + if len(cmd.smartContractToken) < 46 || !strings.HasPrefix(cmd.smartContractToken, "Qm") { + cmd.log.Error("Invalid smart contract token") + return + } + if !strings.HasPrefix(cmd.did, "bafybmi") || len(cmd.did) < 59 { + cmd.log.Error("Invalid DID") + return + } + if cmd.publishType < 0 || cmd.publishType > 1 { + cmd.log.Error("Invalid publish type") + return + } basicResponse, err := cmd.c.PublishNewEvent(cmd.smartContractToken, cmd.did, cmd.publishType, cmd.newContractBlock) if err != nil { @@ -74,6 +109,10 @@ func (cmd *Command) PublishContract() { cmd.log.Info("New event published successfully") } func (cmd *Command) SubscribeContract() { + if len(cmd.smartContractToken) < 46 || !strings.HasPrefix(cmd.smartContractToken, "Qm") { + cmd.log.Error("Invalid smart contract token") + return + } basicResponse, err := cmd.c.SubscribeContract(cmd.smartContractToken) @@ -95,6 +134,22 @@ func (cmd *Command) SubscribeContract() { } func (cmd *Command) deploySmartcontract() { + if len(cmd.smartContractToken) < 46 || !strings.HasPrefix(cmd.smartContractToken, "Qm") { + cmd.log.Error("Invalid smart contract token") + return + } + if !strings.HasPrefix(cmd.deployerAddr, "bafybmi") || len(cmd.deployerAddr) < 59 { + cmd.log.Error("Invalid deployer DID") + return + } + if cmd.rbtAmount == 0.0 || cmd.rbtAmount < 0.00001 { + cmd.log.Error("Invalid RBT amount") + return + } + if cmd.transType < 0 || cmd.transType > 2 { + cmd.log.Error("Invalid trans type") + return + } deployRequest := model.DeploySmartContractRequest{ SmartContractToken: cmd.smartContractToken, DeployerAddress: cmd.deployerAddr, @@ -117,6 +172,26 @@ func (cmd *Command) deploySmartcontract() { } func (cmd *Command) executeSmartcontract() { + if len(cmd.smartContractToken) < 46 || !strings.HasPrefix(cmd.smartContractToken, "Qm") { + cmd.log.Error("Invalid smart contract token") + return + } + if !strings.HasPrefix(cmd.executorAddr, "bafybmi") || len(cmd.executorAddr) < 59 { + cmd.log.Error("Invalid executer DID") + return + } + if cmd.transType < 0 || cmd.transType > 2 { + cmd.log.Error("Invalid trans type") + return + } + if cmd.smartContractData == "" { + fmt.Print("Enter Data to be executed : ") + _, err := fmt.Scan(&cmd.smartContractData) + if err != nil { + cmd.log.Error("Failed to get data") + return + } + } executorRequest := model.ExecuteSmartContractRequest{ SmartContractToken: cmd.smartContractToken, ExecutorAddress: cmd.executorAddr, diff --git a/command/token.go b/command/token.go index 9e2e6bce..814e79e3 100644 --- a/command/token.go +++ b/command/token.go @@ -1,6 +1,16 @@ package command +import "strings" + func (cmd *Command) GenerateTestRBT() { + if !strings.HasPrefix(cmd.did, "bafybmi") || len(cmd.did) < 59 { + cmd.log.Error("Invalid DID") + return + } + if cmd.numTokens <= 0 { + cmd.log.Error("Invalid RBT amount, tokens generated should be a whole number and greater than 0") + return + } br, err := cmd.c.GenerateTestRBT(cmd.numTokens, cmd.did) diff --git a/command/transfer.go b/command/transfer.go index 46c28f8c..19358bd8 100644 --- a/command/transfer.go +++ b/command/transfer.go @@ -1,10 +1,47 @@ package command import ( + "fmt" + "strings" + "github.com/rubixchain/rubixgoplatform/core/model" ) func (cmd *Command) TransferRBT() { + if cmd.senderAddr == "" { + cmd.log.Info("Sender address cannot be empty") + fmt.Print("Enter Sender DID : ") + _, err := fmt.Scan(&cmd.senderAddr) + if err != nil { + cmd.log.Error("Failed to get Sender DID") + return + } + } + if cmd.receiverAddr == "" { + cmd.log.Info("Receiver address cannot be empty") + fmt.Print("Enter Receiver DID : ") + _, err := fmt.Scan(&cmd.receiverAddr) + if err != nil { + cmd.log.Error("Failed to get Receiver DID") + return + } + } + if strings.Contains(cmd.senderAddr, ".") || strings.Contains(cmd.receiverAddr, ".") { + cmd.log.Error("Invalid sender or receiver address. Please provide valid DID") + return + } + if !strings.HasPrefix(cmd.senderAddr, "bafybmi") || len(cmd.senderAddr) < 59 || !strings.HasPrefix(cmd.receiverAddr, "bafybmi") || len(cmd.receiverAddr) < 59 { + cmd.log.Error("Invalid sender or receiver DID") + return + } + if cmd.rbtAmount == 0.0 || cmd.rbtAmount < 0.00001 { + cmd.log.Error("Invalid RBT amount") + return + } + if cmd.transType < 0 || cmd.transType > 2 { + cmd.log.Error("Invalid trans type") + return + } rt := model.RBTTransferRequest{ Receiver: cmd.receiverAddr, Sender: cmd.senderAddr, diff --git a/command/txndetails.go b/command/txndetails.go index ed12e61d..7d8222fe 100644 --- a/command/txndetails.go +++ b/command/txndetails.go @@ -1,8 +1,19 @@ package command -import "fmt" +import ( + "fmt" + "strings" +) func (cmd *Command) getTxnDetails() { + if cmd.did == "" && cmd.txnID == "" && cmd.transComment == "" { + cmd.log.Error("Please provide did or transaction id or transaction comment to get transaction details") + return + } + if cmd.did != "" && !strings.HasPrefix(cmd.did, "bafybmi") || len(cmd.did) < 59 { + cmd.log.Error("Invalid DID") + return + } if cmd.txnID != "" { res, err := cmd.c.GetTxnByID(cmd.txnID) if err != nil { From 620cd0bfa9e822f482cff0b48eebcc8d26bbf76b Mon Sep 17 00:00:00 2001 From: Ashita Gupta Date: Tue, 9 Jul 2024 04:12:57 +0530 Subject: [PATCH 083/129] updating minor changes --- client/quorum.go | 8 ++++-- command/bootstrap.go | 17 ++++++++++++ command/data_token.go | 18 +++++++++++++ command/diagnostic.go | 18 +++++++++++++ command/did.go | 18 +++++++++++++ command/ping.go | 13 +++++++++ command/smartContract.go | 58 ++++++++++++++++++++++++++++++++++++++-- command/token.go | 14 +++++++++- command/transfer.go | 2 +- command/txndetails.go | 4 +++ 10 files changed, 164 insertions(+), 6 deletions(-) diff --git a/client/quorum.go b/client/quorum.go index 9b4c31ae..ec6ba193 100644 --- a/client/quorum.go +++ b/client/quorum.go @@ -2,7 +2,7 @@ package client import ( "encoding/json" - "io/ioutil" + "os" "github.com/rubixchain/rubixgoplatform/core" "github.com/rubixchain/rubixgoplatform/core/model" @@ -14,7 +14,7 @@ func (c *Client) AddQuorum(quorumList string) (string, bool) { c.log.Error("Quorum list required") return "Quorum list required", false } - qlb, err := ioutil.ReadFile(quorumList) + qlb, err := os.ReadFile(quorumList) if err != nil { c.log.Error("Invalid file", "err", err) return "Invalid file, failed to add quorum list", false @@ -25,6 +25,10 @@ func (c *Client) AddQuorum(quorumList string) (string, bool) { c.log.Error("Invalid file, failed to add quorum list", "err", err) return "Invalid file, failed to add quorum list", false } + if len(ql) == 0 { + c.log.Error("Quorum list provided is empty") + return "Quorum list provided is empty", false + } var resp model.BasicResponse err = c.sendJSONRequest("POST", setup.APIAddQuorum, nil, &ql, &resp) if err != nil { diff --git a/command/bootstrap.go b/command/bootstrap.go index 666789a0..cc2286c6 100644 --- a/command/bootstrap.go +++ b/command/bootstrap.go @@ -1,10 +1,21 @@ package command +import ( + "fmt" + "strings" +) + func (cmd *Command) addBootStrap() { if len(cmd.peers) == 0 { cmd.log.Error("Peers required for bootstrap. Use flag -peers to provide peers separated by a ','") return } + for _, peer := range cmd.peers { + if !strings.HasSuffix(peer, "/") { + cmd.log.Error(fmt.Sprintf("Invalid bootstrap peer : %s", peer)) + return + } + } msg, status := cmd.c.AddBootStrap(cmd.peers) if !status { @@ -19,6 +30,12 @@ func (cmd *Command) removeBootStrap() { cmd.log.Error("Peers required for bootstrap. Use flag -peers to provide peers separated by a ','") return } + for _, peer := range cmd.peers { + if !strings.HasSuffix(peer, "/") { + cmd.log.Error(fmt.Sprintf("Invalid bootstrap peer : %s", peer)) + return + } + } msg, status := cmd.c.RemoveBootStrap(cmd.peers) if !status { cmd.log.Error("Remove bootstrap command failed, " + msg) diff --git a/command/data_token.go b/command/data_token.go index 7d442c09..e7f06d95 100644 --- a/command/data_token.go +++ b/command/data_token.go @@ -13,6 +13,15 @@ import ( ) func (cmd *Command) createDataToken() { + if cmd.did == "" { + cmd.log.Info("DID cannot be empty") + fmt.Print("Enter DID : ") + _, err := fmt.Scan(&cmd.did) + if err != nil { + cmd.log.Error("Failed to get DID") + return + } + } if !strings.HasPrefix(cmd.did, "bafybmi") || len(cmd.did) < 59 { cmd.log.Error("Invalid DID") return @@ -64,6 +73,15 @@ func (cmd *Command) createDataToken() { } func (cmd *Command) commitDataToken() { + if cmd.did == "" { + cmd.log.Info("DID cannot be empty") + fmt.Print("Enter DID : ") + _, err := fmt.Scan(&cmd.did) + if err != nil { + cmd.log.Error("Failed to get DID") + return + } + } if !strings.HasPrefix(cmd.did, "bafybmi") || len(cmd.did) < 59 { cmd.log.Error("Invalid DID") return diff --git a/command/diagnostic.go b/command/diagnostic.go index e9c3f287..ca271abd 100644 --- a/command/diagnostic.go +++ b/command/diagnostic.go @@ -134,6 +134,15 @@ func tcMarshal(str string, m interface{}) (string, error) { } func (cmd *Command) dumpTokenChain() { + if cmd.token == "" { + cmd.log.Info("token id cannot be empty") + fmt.Print("Enter Token Id : ") + _, err := fmt.Scan(&cmd.token) + if err != nil { + cmd.log.Error("Failed to get Token ID") + return + } + } if len(cmd.token) < 46 || !strings.HasPrefix(cmd.token, "Qm") { cmd.log.Error("Invalid smart contract token") return @@ -180,6 +189,15 @@ func (cmd *Command) dumpTokenChain() { } func (cmd *Command) dumpSmartContractTokenChain() { + if cmd.smartContractToken == "" { + cmd.log.Info("smart contract token id cannot be empty") + fmt.Print("Enter SC Token Id : ") + _, err := fmt.Scan(&cmd.smartContractToken) + if err != nil { + cmd.log.Error("Failed to get SC Token ID") + return + } + } if len(cmd.smartContractToken) < 46 || !strings.HasPrefix(cmd.smartContractToken, "Qm") { cmd.log.Error("Invalid smart contract token") return diff --git a/command/did.go b/command/did.go index 30c72cff..14ffc7a1 100644 --- a/command/did.go +++ b/command/did.go @@ -185,6 +185,15 @@ func (cmd *Command) GetAllDID() { } func (cmd *Command) RegsiterDIDCmd() { + if cmd.did == "" { + cmd.log.Info("DID cannot be empty") + fmt.Print("Enter DID : ") + _, err := fmt.Scan(&cmd.did) + if err != nil { + cmd.log.Error("Failed to get DID") + return + } + } if !strings.HasPrefix(cmd.did, "bafybmi") || len(cmd.did) < 59 { cmd.log.Error("Invalid DID") return @@ -335,6 +344,15 @@ func (cmd *Command) SignatureResponse(br *model.BasicResponse, timeout ...time.D } func (cmd *Command) GetAccountInfo() { + if cmd.did == "" { + cmd.log.Info("DID cannot be empty") + fmt.Print("Enter DID : ") + _, err := fmt.Scan(&cmd.did) + if err != nil { + cmd.log.Error("Failed to get DID") + return + } + } if !strings.HasPrefix(cmd.did, "bafybmi") || len(cmd.did) < 59 { cmd.log.Error("Invalid DID") return diff --git a/command/ping.go b/command/ping.go index f00b115f..02c08067 100644 --- a/command/ping.go +++ b/command/ping.go @@ -32,6 +32,19 @@ func (cmd *Command) checkQuorumStatus() { return } } + parts := strings.Split(cmd.quorumAddr, ".") + if len(parts) != 2 { + cmd.log.Error("Invalid quorum address") + return + } + if !strings.HasPrefix(parts[0], "12D3KooW") || len(parts[0]) < 52 { + cmd.log.Error("Invalid PeerID of the quorum") + return + } + if !strings.HasPrefix(parts[1], "bafybmi") || len(parts[1]) < 59 { + cmd.log.Error("Invalid DID of the quorum") + return + } msg, _ := cmd.c.CheckQuorumStatus(cmd.quorumAddr) //Verification with "status" pending ! if strings.Contains(msg, "Quorum is setup") { diff --git a/command/smartContract.go b/command/smartContract.go index 4acc52c9..ddd0f923 100644 --- a/command/smartContract.go +++ b/command/smartContract.go @@ -10,6 +10,15 @@ import ( ) func (cmd *Command) generateSmartContractToken() { + if cmd.did == "" { + cmd.log.Info("DID cannot be empty") + fmt.Print("Enter DID : ") + _, err := fmt.Scan(&cmd.did) + if err != nil { + cmd.log.Error("Failed to get DID") + return + } + } if !strings.HasPrefix(cmd.did, "bafybmi") || len(cmd.did) < 59 { cmd.log.Error("Invalid DID") return @@ -54,6 +63,15 @@ func (cmd *Command) generateSmartContractToken() { } func (cmd *Command) fetchSmartContract() { + if cmd.smartContractToken == "" { + cmd.log.Info("smart contract token id cannot be empty") + fmt.Print("Enter SC Token Id : ") + _, err := fmt.Scan(&cmd.smartContractToken) + if err != nil { + cmd.log.Error("Failed to get SC Token ID") + return + } + } if len(cmd.smartContractToken) < 46 || !strings.HasPrefix(cmd.smartContractToken, "Qm") { cmd.log.Error("Invalid smart contract token") return @@ -78,6 +96,15 @@ func (cmd *Command) fetchSmartContract() { cmd.log.Info("Smart contract token fetched successfully") } func (cmd *Command) PublishContract() { + if cmd.smartContractToken == "" { + cmd.log.Info("smart contract token id cannot be empty") + fmt.Print("Enter SC Token Id : ") + _, err := fmt.Scan(&cmd.smartContractToken) + if err != nil { + cmd.log.Error("Failed to get SC Token ID") + return + } + } if len(cmd.smartContractToken) < 46 || !strings.HasPrefix(cmd.smartContractToken, "Qm") { cmd.log.Error("Invalid smart contract token") return @@ -109,6 +136,15 @@ func (cmd *Command) PublishContract() { cmd.log.Info("New event published successfully") } func (cmd *Command) SubscribeContract() { + if cmd.smartContractToken == "" { + cmd.log.Info("smart contract token id cannot be empty") + fmt.Print("Enter SC Token Id : ") + _, err := fmt.Scan(&cmd.smartContractToken) + if err != nil { + cmd.log.Error("Failed to get SC Token ID") + return + } + } if len(cmd.smartContractToken) < 46 || !strings.HasPrefix(cmd.smartContractToken, "Qm") { cmd.log.Error("Invalid smart contract token") return @@ -134,6 +170,15 @@ func (cmd *Command) SubscribeContract() { } func (cmd *Command) deploySmartcontract() { + if cmd.smartContractToken == "" { + cmd.log.Info("smart contract token id cannot be empty") + fmt.Print("Enter SC Token Id : ") + _, err := fmt.Scan(&cmd.smartContractToken) + if err != nil { + cmd.log.Error("Failed to get SC Token ID") + return + } + } if len(cmd.smartContractToken) < 46 || !strings.HasPrefix(cmd.smartContractToken, "Qm") { cmd.log.Error("Invalid smart contract token") return @@ -146,7 +191,7 @@ func (cmd *Command) deploySmartcontract() { cmd.log.Error("Invalid RBT amount") return } - if cmd.transType < 0 || cmd.transType > 2 { + if cmd.transType < 1 || cmd.transType > 2 { cmd.log.Error("Invalid trans type") return } @@ -172,6 +217,15 @@ func (cmd *Command) deploySmartcontract() { } func (cmd *Command) executeSmartcontract() { + if cmd.smartContractToken == "" { + cmd.log.Info("smart contract token id cannot be empty") + fmt.Print("Enter SC Token Id : ") + _, err := fmt.Scan(&cmd.smartContractToken) + if err != nil { + cmd.log.Error("Failed to get SC Token ID") + return + } + } if len(cmd.smartContractToken) < 46 || !strings.HasPrefix(cmd.smartContractToken, "Qm") { cmd.log.Error("Invalid smart contract token") return @@ -180,7 +234,7 @@ func (cmd *Command) executeSmartcontract() { cmd.log.Error("Invalid executer DID") return } - if cmd.transType < 0 || cmd.transType > 2 { + if cmd.transType < 1 || cmd.transType > 2 { cmd.log.Error("Invalid trans type") return } diff --git a/command/token.go b/command/token.go index 814e79e3..dbeacaa5 100644 --- a/command/token.go +++ b/command/token.go @@ -1,8 +1,20 @@ package command -import "strings" +import ( + "fmt" + "strings" +) func (cmd *Command) GenerateTestRBT() { + if cmd.did == "" { + cmd.log.Info("DID cannot be empty") + fmt.Print("Enter DID : ") + _, err := fmt.Scan(&cmd.did) + if err != nil { + cmd.log.Error("Failed to get DID") + return + } + } if !strings.HasPrefix(cmd.did, "bafybmi") || len(cmd.did) < 59 { cmd.log.Error("Invalid DID") return diff --git a/command/transfer.go b/command/transfer.go index 19358bd8..276abf16 100644 --- a/command/transfer.go +++ b/command/transfer.go @@ -38,7 +38,7 @@ func (cmd *Command) TransferRBT() { cmd.log.Error("Invalid RBT amount") return } - if cmd.transType < 0 || cmd.transType > 2 { + if cmd.transType < 1 || cmd.transType > 2 { cmd.log.Error("Invalid trans type") return } diff --git a/command/txndetails.go b/command/txndetails.go index 7d8222fe..6fd4ba6e 100644 --- a/command/txndetails.go +++ b/command/txndetails.go @@ -30,6 +30,10 @@ func (cmd *Command) getTxnDetails() { } if cmd.did != "" { + if !strings.HasPrefix(cmd.did, "bafybmi") || len(cmd.did) < 59 { + cmd.log.Error("Invalid DID") + return + } res, err := cmd.c.GetTxnByDID(cmd.did, cmd.role) if err != nil { cmd.log.Error("Invalid response from the node", "err", err) From 8d3782016b9f9b9cb19668948022128d65f0e8bb Mon Sep 17 00:00:00 2001 From: KryptSai Date: Tue, 9 Jul 2024 14:32:12 +0530 Subject: [PATCH 084/129] removing the debug statements --- core/smart_contract.go | 3 --- 1 file changed, 3 deletions(-) diff --git a/core/smart_contract.go b/core/smart_contract.go index b60cd634..80834e9a 100644 --- a/core/smart_contract.go +++ b/core/smart_contract.go @@ -368,13 +368,10 @@ func (c *Core) ContractCallBack(peerID string, topic string, data []byte) { } c.FetchSmartContract(requestID, &fetchSC) c.log.Info("Smart contract " + fetchSC.SmartContractToken + " files fetching succesful") - c.log.Debug("SmartContractTokenPath", fetchSC.SmartContractTokenPath) } smartContractToken := newEvent.SmartContractToken scFolderPath := c.cfg.DirPath + "SmartContract/" + smartContractToken - c.log.Debug("scfolderpath", scFolderPath) if _, err := os.Stat(scFolderPath); os.IsNotExist(err) { - c.log.Debug("sc folder path does not exist") fetchSC.SmartContractToken = smartContractToken fetchSC.SmartContractTokenPath, err = c.CreateSCTempFolder() if err != nil { From 82335a2615a6dbc8c362e12cdb3a605c05698152 Mon Sep 17 00:00:00 2001 From: Ashita Gupta Date: Tue, 9 Jul 2024 18:27:00 +0530 Subject: [PATCH 085/129] adding checks at API side and updating CheckQuorumStatusCmd --- client/ping.go | 7 ---- client/quorum.go | 16 ++++++-- command/addingpeerdetails.go | 7 +++- command/data_token.go | 7 +++- command/diagnostic.go | 11 ++++-- command/did.go | 10 +++-- command/explorer.go | 4 +- command/ping.go | 16 +++----- command/quorurm.go | 4 +- command/smartContract.go | 37 ++++++++++++------ command/token.go | 4 +- command/transfer.go | 13 +++--- command/txndetails.go | 9 ++--- core/ping.go | 3 ++ server/addpeer.go | 7 +++- server/basic.go | 31 +++++++++------ server/config.go | 43 ++++++++++++++++++++ server/data_token.go | 17 ++++++++ server/diagnostic.go | 12 ++++++ server/did.go | 16 ++++++++ server/migration.go | 4 ++ server/quorum.go | 8 ++++ server/smart_contract.go | 76 +++++++++++++++++++++++++++++++++++- server/tokens.go | 41 +++++++++++++++++++ server/txndetails.go | 7 ++++ 25 files changed, 338 insertions(+), 72 deletions(-) diff --git a/client/ping.go b/client/ping.go index 3b613d57..ae8eb430 100644 --- a/client/ping.go +++ b/client/ping.go @@ -1,7 +1,6 @@ package client import ( - "strings" "time" "github.com/rubixchain/rubixgoplatform/core/model" @@ -21,12 +20,6 @@ func (c *Client) Ping(peerID string) (string, bool) { func (c *Client) CheckQuorumStatus(quorumAddress string) (string, bool) { q := make(map[string]string) - // Split the string into two parts based on a delimiter - parts := strings.Split(quorumAddress, ".") - if len(parts) != 2 { - // Handle the case where the string doesn't contain exactly two parts - return "Invalid quorumAddress format", false - } q["quorumAddress"] = quorumAddress var rm model.BasicResponse err := c.sendJSONRequest("GET", setup.APICheckQuorumStatus, q, nil, &rm, 2*time.Minute) diff --git a/client/quorum.go b/client/quorum.go index ec6ba193..0c951072 100644 --- a/client/quorum.go +++ b/client/quorum.go @@ -2,7 +2,10 @@ package client import ( "encoding/json" + "fmt" "os" + "regexp" + "strings" "github.com/rubixchain/rubixgoplatform/core" "github.com/rubixchain/rubixgoplatform/core/model" @@ -25,9 +28,16 @@ func (c *Client) AddQuorum(quorumList string) (string, bool) { c.log.Error("Invalid file, failed to add quorum list", "err", err) return "Invalid file, failed to add quorum list", false } - if len(ql) == 0 { - c.log.Error("Quorum list provided is empty") - return "Quorum list provided is empty", false + if len(ql) < 5 { + c.log.Error("Length of Quorum list should be atleast 5") + return "Length of Quorum list should be atleast 5", false + } + for _, q := range ql { + is_alphanumeric := regexp.MustCompile(`^[a-zA-Z0-9]*$`).MatchString(q.Address) + if !strings.HasPrefix(q.Address, "bafybmi") || len(q.Address) != 59 || !is_alphanumeric { + c.log.Error(fmt.Sprintf("Invalid quorum DID : %s", q.Address)) + return fmt.Sprintf("Invalid quorum DID : %s", q.Address), false + } } var resp model.BasicResponse err = c.sendJSONRequest("POST", setup.APIAddQuorum, nil, &ql, &resp) diff --git a/command/addingpeerdetails.go b/command/addingpeerdetails.go index 9e911dde..8b09802d 100644 --- a/command/addingpeerdetails.go +++ b/command/addingpeerdetails.go @@ -2,6 +2,7 @@ package command import ( "fmt" + "regexp" "strings" "github.com/rubixchain/rubixgoplatform/core/wallet" @@ -21,7 +22,8 @@ func (cmd *Command) AddPeerDetails() { } else { peerID = cmd.peerID } - if !strings.HasPrefix(peerID, "12D3KooW") || len(peerID) < 52 { + is_alphanumeric := regexp.MustCompile(`^[a-zA-Z0-9]*$`).MatchString(cmd.peerID) + if !strings.HasPrefix(cmd.peerID, "12D3KooW") || len(cmd.peerID) != 52 || !is_alphanumeric { cmd.log.Error("Invalid PeerID") return } @@ -36,7 +38,8 @@ func (cmd *Command) AddPeerDetails() { } else { did = cmd.did } - if !strings.HasPrefix(did, "bafybmi") || len(did) < 59 { + is_alphanumeric = regexp.MustCompile(`^[a-zA-Z0-9]*$`).MatchString(cmd.did) + if !strings.HasPrefix(cmd.did, "bafybmi") || len(cmd.did) != 59 || !is_alphanumeric { cmd.log.Error("Invalid DID") return } diff --git a/command/data_token.go b/command/data_token.go index e7f06d95..117f13f7 100644 --- a/command/data_token.go +++ b/command/data_token.go @@ -5,6 +5,7 @@ import ( "fmt" "io/ioutil" "path" + "regexp" "strings" "github.com/rubixchain/rubixgoplatform/client" @@ -22,7 +23,8 @@ func (cmd *Command) createDataToken() { return } } - if !strings.HasPrefix(cmd.did, "bafybmi") || len(cmd.did) < 59 { + is_alphanumeric := regexp.MustCompile(`^[a-zA-Z0-9]*$`).MatchString(cmd.did) + if !strings.HasPrefix(cmd.did, "bafybmi") || len(cmd.did) != 59 || !is_alphanumeric { cmd.log.Error("Invalid DID") return } @@ -82,7 +84,8 @@ func (cmd *Command) commitDataToken() { return } } - if !strings.HasPrefix(cmd.did, "bafybmi") || len(cmd.did) < 59 { + is_alphanumeric := regexp.MustCompile(`^[a-zA-Z0-9]*$`).MatchString(cmd.did) + if !strings.HasPrefix(cmd.did, "bafybmi") || len(cmd.did) != 59 || !is_alphanumeric { cmd.log.Error("Invalid DID") return } diff --git a/command/diagnostic.go b/command/diagnostic.go index ca271abd..150f4db6 100644 --- a/command/diagnostic.go +++ b/command/diagnostic.go @@ -3,6 +3,7 @@ package command import ( "fmt" "os" + "regexp" "strings" "github.com/rubixchain/rubixgoplatform/block" @@ -143,8 +144,10 @@ func (cmd *Command) dumpTokenChain() { return } } - if len(cmd.token) < 46 || !strings.HasPrefix(cmd.token, "Qm") { - cmd.log.Error("Invalid smart contract token") + is_alphanumeric := regexp.MustCompile(`^[a-zA-Z0-9]*$`).MatchString(cmd.token) + + if len(cmd.token) != 46 || !strings.HasPrefix(cmd.token, "Qm") || !is_alphanumeric { + cmd.log.Error("Invalid token") return } @@ -198,7 +201,9 @@ func (cmd *Command) dumpSmartContractTokenChain() { return } } - if len(cmd.smartContractToken) < 46 || !strings.HasPrefix(cmd.smartContractToken, "Qm") { + is_alphanumeric := regexp.MustCompile(`^[a-zA-Z0-9]*$`).MatchString(cmd.smartContractToken) + + if len(cmd.smartContractToken) != 46 || !strings.HasPrefix(cmd.smartContractToken, "Qm") || !is_alphanumeric { cmd.log.Error("Invalid smart contract token") return } diff --git a/command/did.go b/command/did.go index 14ffc7a1..1785ae20 100644 --- a/command/did.go +++ b/command/did.go @@ -6,6 +6,7 @@ import ( "image" "io/ioutil" "os" + "regexp" "strings" "time" @@ -194,7 +195,8 @@ func (cmd *Command) RegsiterDIDCmd() { return } } - if !strings.HasPrefix(cmd.did, "bafybmi") || len(cmd.did) < 59 { + is_alphanumeric := regexp.MustCompile(`^[a-zA-Z0-9]*$`).MatchString(cmd.did) + if !strings.HasPrefix(cmd.did, "bafybmi") || len(cmd.did) != 59 || !is_alphanumeric { cmd.log.Error("Invalid DID") return } @@ -220,7 +222,8 @@ func (cmd *Command) RegsiterDIDCmd() { } func (cmd *Command) SetupDIDCmd() { - if !strings.HasPrefix(cmd.did, "bafybmi") || len(cmd.did) < 59 { + is_alphanumeric := regexp.MustCompile(`^[a-zA-Z0-9]*$`).MatchString(cmd.did) + if !strings.HasPrefix(cmd.did, "bafybmi") || len(cmd.did) != 59 || !is_alphanumeric { cmd.log.Error("Invalid DID") return } @@ -353,7 +356,8 @@ func (cmd *Command) GetAccountInfo() { return } } - if !strings.HasPrefix(cmd.did, "bafybmi") || len(cmd.did) < 59 { + is_alphanumeric := regexp.MustCompile(`^[a-zA-Z0-9]*$`).MatchString(cmd.did) + if !strings.HasPrefix(cmd.did, "bafybmi") || len(cmd.did) != 59 || !is_alphanumeric { cmd.log.Error("Invalid DID") return } diff --git a/command/explorer.go b/command/explorer.go index 01b1552b..11070427 100644 --- a/command/explorer.go +++ b/command/explorer.go @@ -4,7 +4,7 @@ import "fmt" func (cmd *Command) addExplorer() { if len(cmd.links) == 0 { - cmd.log.Error("links required for Explorer") + cmd.log.Error("provide explorer links required to add") return } msg, status := cmd.c.AddExplorer(cmd.links) @@ -18,7 +18,7 @@ func (cmd *Command) addExplorer() { func (cmd *Command) removeExplorer() { if len(cmd.links) == 0 { - cmd.log.Error("links required for Explorer") + cmd.log.Error("provide explorer links required to remove") return } msg, status := cmd.c.RemoveExplorer(cmd.links) diff --git a/command/ping.go b/command/ping.go index 02c08067..d64c3197 100644 --- a/command/ping.go +++ b/command/ping.go @@ -2,6 +2,7 @@ package command import ( "fmt" + "regexp" "strings" ) @@ -10,7 +11,8 @@ func (cmd *Command) ping() { cmd.log.Error("PeerID cannot be empty. Please use flag peerId") return } - if !strings.HasPrefix(cmd.peerID, "12D3KooW") || len(cmd.peerID) < 52 { + is_alphanumeric := regexp.MustCompile(`^[a-zA-Z0-9]*$`).MatchString(cmd.peerID) + if !strings.HasPrefix(cmd.peerID, "12D3KooW") || len(cmd.peerID) != 52 || !is_alphanumeric { cmd.log.Error("Invalid PeerID") return } @@ -32,16 +34,8 @@ func (cmd *Command) checkQuorumStatus() { return } } - parts := strings.Split(cmd.quorumAddr, ".") - if len(parts) != 2 { - cmd.log.Error("Invalid quorum address") - return - } - if !strings.HasPrefix(parts[0], "12D3KooW") || len(parts[0]) < 52 { - cmd.log.Error("Invalid PeerID of the quorum") - return - } - if !strings.HasPrefix(parts[1], "bafybmi") || len(parts[1]) < 59 { + is_alphanumeric := regexp.MustCompile(`^[a-zA-Z0-9]*$`).MatchString(cmd.quorumAddr) + if !strings.HasPrefix(cmd.quorumAddr, "bafybmi") || len(cmd.quorumAddr) != 59 || !is_alphanumeric { cmd.log.Error("Invalid DID of the quorum") return } diff --git a/command/quorurm.go b/command/quorurm.go index 7060908e..af1dce3d 100644 --- a/command/quorurm.go +++ b/command/quorurm.go @@ -2,6 +2,7 @@ package command import ( "fmt" + "regexp" "strings" ) @@ -58,7 +59,8 @@ func (cmd *Command) SetupQuorum() { return } } - if !strings.HasPrefix(cmd.did, "bafybmi") || len(cmd.did) < 59 { + is_alphanumeric := regexp.MustCompile(`^[a-zA-Z0-9]*$`).MatchString(cmd.did) + if !strings.HasPrefix(cmd.did, "bafybmi") || len(cmd.did) != 59 || !is_alphanumeric { cmd.log.Error("Invalid DID") return } diff --git a/command/smartContract.go b/command/smartContract.go index ddd0f923..61184f8e 100644 --- a/command/smartContract.go +++ b/command/smartContract.go @@ -2,6 +2,7 @@ package command import ( "fmt" + "regexp" "strings" "github.com/rubixchain/rubixgoplatform/client" @@ -19,7 +20,8 @@ func (cmd *Command) generateSmartContractToken() { return } } - if !strings.HasPrefix(cmd.did, "bafybmi") || len(cmd.did) < 59 { + is_alphanumeric := regexp.MustCompile(`^[a-zA-Z0-9]*$`).MatchString(cmd.did) + if !strings.HasPrefix(cmd.did, "bafybmi") || len(cmd.did) != 59 || !is_alphanumeric { cmd.log.Error("Invalid DID") return } @@ -72,7 +74,9 @@ func (cmd *Command) fetchSmartContract() { return } } - if len(cmd.smartContractToken) < 46 || !strings.HasPrefix(cmd.smartContractToken, "Qm") { + is_alphanumeric := regexp.MustCompile(`^[a-zA-Z0-9]*$`).MatchString(cmd.smartContractToken) + + if len(cmd.smartContractToken) != 46 || !strings.HasPrefix(cmd.smartContractToken, "Qm") || !is_alphanumeric { cmd.log.Error("Invalid smart contract token") return } @@ -105,15 +109,17 @@ func (cmd *Command) PublishContract() { return } } - if len(cmd.smartContractToken) < 46 || !strings.HasPrefix(cmd.smartContractToken, "Qm") { + is_alphanumeric := regexp.MustCompile(`^[a-zA-Z0-9]*$`).MatchString(cmd.smartContractToken) + if len(cmd.smartContractToken) != 46 || !strings.HasPrefix(cmd.smartContractToken, "Qm") || !is_alphanumeric { cmd.log.Error("Invalid smart contract token") return } - if !strings.HasPrefix(cmd.did, "bafybmi") || len(cmd.did) < 59 { + is_alphanumeric = regexp.MustCompile(`^[a-zA-Z0-9]*$`).MatchString(cmd.did) + if !strings.HasPrefix(cmd.did, "bafybmi") || len(cmd.did) != 59 || !is_alphanumeric { cmd.log.Error("Invalid DID") return } - if cmd.publishType < 0 || cmd.publishType > 1 { + if cmd.publishType < 1 || cmd.publishType > 2 { cmd.log.Error("Invalid publish type") return } @@ -145,7 +151,8 @@ func (cmd *Command) SubscribeContract() { return } } - if len(cmd.smartContractToken) < 46 || !strings.HasPrefix(cmd.smartContractToken, "Qm") { + is_alphanumeric := regexp.MustCompile(`^[a-zA-Z0-9]*$`).MatchString(cmd.smartContractToken) + if len(cmd.smartContractToken) != 46 || !strings.HasPrefix(cmd.smartContractToken, "Qm") || !is_alphanumeric { cmd.log.Error("Invalid smart contract token") return } @@ -179,16 +186,18 @@ func (cmd *Command) deploySmartcontract() { return } } - if len(cmd.smartContractToken) < 46 || !strings.HasPrefix(cmd.smartContractToken, "Qm") { + is_alphanumeric := regexp.MustCompile(`^[a-zA-Z0-9]*$`).MatchString(cmd.smartContractToken) + if len(cmd.smartContractToken) != 46 || !strings.HasPrefix(cmd.smartContractToken, "Qm") || !is_alphanumeric { cmd.log.Error("Invalid smart contract token") return } - if !strings.HasPrefix(cmd.deployerAddr, "bafybmi") || len(cmd.deployerAddr) < 59 { + is_alphanumeric = regexp.MustCompile(`^[a-zA-Z0-9]*$`).MatchString(cmd.deployerAddr) + if !strings.HasPrefix(cmd.deployerAddr, "bafybmi") || len(cmd.deployerAddr) != 59 || !is_alphanumeric { cmd.log.Error("Invalid deployer DID") return } - if cmd.rbtAmount == 0.0 || cmd.rbtAmount < 0.00001 { - cmd.log.Error("Invalid RBT amount") + if cmd.rbtAmount < 0.00001 { + cmd.log.Error("Invalid RBT amount. Minimum RBT amount should be 0.00001") return } if cmd.transType < 1 || cmd.transType > 2 { @@ -226,11 +235,15 @@ func (cmd *Command) executeSmartcontract() { return } } - if len(cmd.smartContractToken) < 46 || !strings.HasPrefix(cmd.smartContractToken, "Qm") { + + is_alphanumeric := regexp.MustCompile(`^[a-zA-Z0-9]*$`).MatchString(cmd.smartContractToken) + if len(cmd.smartContractToken) != 46 || !strings.HasPrefix(cmd.smartContractToken, "Qm") || !is_alphanumeric { cmd.log.Error("Invalid smart contract token") return } - if !strings.HasPrefix(cmd.executorAddr, "bafybmi") || len(cmd.executorAddr) < 59 { + + is_alphanumeric = regexp.MustCompile(`^[a-zA-Z0-9]*$`).MatchString(cmd.executorAddr) + if !strings.HasPrefix(cmd.executorAddr, "bafybmi") || len(cmd.executorAddr) != 59 || !is_alphanumeric { cmd.log.Error("Invalid executer DID") return } diff --git a/command/token.go b/command/token.go index dbeacaa5..43ed856b 100644 --- a/command/token.go +++ b/command/token.go @@ -2,6 +2,7 @@ package command import ( "fmt" + "regexp" "strings" ) @@ -15,7 +16,8 @@ func (cmd *Command) GenerateTestRBT() { return } } - if !strings.HasPrefix(cmd.did, "bafybmi") || len(cmd.did) < 59 { + is_alphanumeric := regexp.MustCompile(`^[a-zA-Z0-9]*$`).MatchString(cmd.did) + if !strings.HasPrefix(cmd.did, "bafybmi") || len(cmd.did) != 59 || !is_alphanumeric { cmd.log.Error("Invalid DID") return } diff --git a/command/transfer.go b/command/transfer.go index 276abf16..deee852f 100644 --- a/command/transfer.go +++ b/command/transfer.go @@ -2,6 +2,7 @@ package command import ( "fmt" + "regexp" "strings" "github.com/rubixchain/rubixgoplatform/core/model" @@ -26,20 +27,22 @@ func (cmd *Command) TransferRBT() { return } } - if strings.Contains(cmd.senderAddr, ".") || strings.Contains(cmd.receiverAddr, ".") { + is_alphanumeric_sender := regexp.MustCompile(`^[a-zA-Z0-9]*$`).MatchString(cmd.did) + is_alphanumeric_receiver := regexp.MustCompile(`^[a-zA-Z0-9]*$`).MatchString(cmd.did) + if !is_alphanumeric_sender || !is_alphanumeric_receiver { cmd.log.Error("Invalid sender or receiver address. Please provide valid DID") return } - if !strings.HasPrefix(cmd.senderAddr, "bafybmi") || len(cmd.senderAddr) < 59 || !strings.HasPrefix(cmd.receiverAddr, "bafybmi") || len(cmd.receiverAddr) < 59 { + if !strings.HasPrefix(cmd.senderAddr, "bafybmi") || len(cmd.senderAddr) != 59 || !strings.HasPrefix(cmd.receiverAddr, "bafybmi") || len(cmd.receiverAddr) != 59 { cmd.log.Error("Invalid sender or receiver DID") return } - if cmd.rbtAmount == 0.0 || cmd.rbtAmount < 0.00001 { - cmd.log.Error("Invalid RBT amount") + if cmd.rbtAmount < 0.00001 { + cmd.log.Error("Invalid RBT amount. RBT amount should be atlease 0.00001") return } if cmd.transType < 1 || cmd.transType > 2 { - cmd.log.Error("Invalid trans type") + cmd.log.Error("Invalid trans type. TransType should be 1 or 2") return } rt := model.RBTTransferRequest{ diff --git a/command/txndetails.go b/command/txndetails.go index 6fd4ba6e..9d0495ac 100644 --- a/command/txndetails.go +++ b/command/txndetails.go @@ -2,6 +2,7 @@ package command import ( "fmt" + "regexp" "strings" ) @@ -10,10 +11,7 @@ func (cmd *Command) getTxnDetails() { cmd.log.Error("Please provide did or transaction id or transaction comment to get transaction details") return } - if cmd.did != "" && !strings.HasPrefix(cmd.did, "bafybmi") || len(cmd.did) < 59 { - cmd.log.Error("Invalid DID") - return - } + if cmd.txnID != "" { res, err := cmd.c.GetTxnByID(cmd.txnID) if err != nil { @@ -30,7 +28,8 @@ func (cmd *Command) getTxnDetails() { } if cmd.did != "" { - if !strings.HasPrefix(cmd.did, "bafybmi") || len(cmd.did) < 59 { + is_alphanumeric := regexp.MustCompile(`^[a-zA-Z0-9]*$`).MatchString(cmd.did) + if !strings.HasPrefix(cmd.did, "bafybmi") || len(cmd.did) != 59 || !is_alphanumeric { cmd.log.Error("Invalid DID") return } diff --git a/core/ping.go b/core/ping.go index e738bc71..eebfb071 100644 --- a/core/ping.go +++ b/core/ping.go @@ -98,6 +98,9 @@ func (c *Core) CheckQuorumStatusResponse(req *ensweb.Request) *ensweb.Result { / // CheckQuorumStatus will ping the peer & get the response func (c *Core) CheckQuorumStatus(peerID string, did string) (string, bool, error) { // q := make(map[string]string) + if peerID == "" { + peerID = c.qm.GetPeerID(did) + } p, err := c.pm.OpenPeerConn(peerID, "", c.getCoreAppName(peerID)) if err != nil { return "Quorum Connection Error", false, fmt.Errorf("quorum connection error") diff --git a/server/addpeer.go b/server/addpeer.go index 62d83357..d1820a01 100644 --- a/server/addpeer.go +++ b/server/addpeer.go @@ -1,6 +1,7 @@ package server import ( + "regexp" "strings" "github.com/rubixchain/rubixgoplatform/core/wallet" @@ -32,10 +33,12 @@ func (s *Server) APIAddPeerDetails(req *ensweb.Request) *ensweb.Result { if pd.DIDType < 0 || pd.DIDType > 4 { return s.BasicResponse(req, false, "Invalid DID Type", nil) } - if !strings.HasPrefix(pd.PeerID, "12D3KooW") || len(pd.PeerID) < 52 { + is_alphanumeric := regexp.MustCompile(`^[a-zA-Z0-9]*$`).MatchString(pd.PeerID) + if !strings.HasPrefix(pd.PeerID, "12D3KooW") || len(pd.PeerID) != 52 || !is_alphanumeric { return s.BasicResponse(req, false, "Invalid Peer ID", nil) } - if !strings.HasPrefix(pd.DID, "bafybmi") || len(pd.DID) < 59 { + is_alphanumeric = regexp.MustCompile(`^[a-zA-Z0-9]*$`).MatchString(pd.DID) + if !strings.HasPrefix(pd.DID, "bafybmi") || len(pd.DID) != 59 || !is_alphanumeric { return s.BasicResponse(req, false, "Invalid DID", nil) } peer_detail.DID = pd.DID diff --git a/server/basic.go b/server/basic.go index 0212226f..4b760a37 100644 --- a/server/basic.go +++ b/server/basic.go @@ -2,6 +2,7 @@ package server import ( "net/http" + "regexp" "strings" "time" @@ -56,8 +57,17 @@ func (s *Server) shutDown() { // APIPing will ping to given peer func (s *Server) APIPing(req *ensweb.Request) *ensweb.Result { - peerdID := s.GetQuerry(req, "peerID") - str, err := s.c.PingPeer(peerdID) + peerID := s.GetQuerry(req, "peerID") + if peerID == "" { + s.log.Error("PeerID cannot be empty") + return s.BasicResponse(req, false, "PeerID cannot be empty", nil) + } + is_alphanumeric := regexp.MustCompile(`^[a-zA-Z0-9]*$`).MatchString(peerID) + if !strings.HasPrefix(peerID, "12D3KooW") || len(peerID) != 52 || !is_alphanumeric { + s.log.Error("Invalid PeerID") + return s.BasicResponse(req, false, "Invalid PeerID", nil) + } + str, err := s.c.PingPeer(peerID) if err != nil { s.log.Error("ping failed", "err", err) return s.BasicResponse(req, false, str, nil) @@ -68,17 +78,14 @@ func (s *Server) APIPing(req *ensweb.Request) *ensweb.Result { // APIPing will ping to given peer func (s *Server) APICheckQuorumStatus(req *ensweb.Request) *ensweb.Result { qAddress := s.GetQuerry(req, "quorumAddress") - // Split the string into two parts based on a delimiter - parts := strings.Split(qAddress, ".") - if len(parts) != 2 { - // Handle the case where the string doesn't contain exactly two parts - s.log.Error("Invalid quorumAddress format, required format is PeerID.dID") - return s.BasicResponse(req, false, "Invalid Quorum Address Format", nil) + DID := qAddress + is_alphanumeric := regexp.MustCompile(`^[a-zA-Z0-9]*$`).MatchString(DID) + if !strings.HasPrefix(DID, "bafybmi") || len(DID) != 59 || !is_alphanumeric { + s.log.Error("Invalid DID of the quorum") + return s.BasicResponse(req, false, "Invalid DID of the quorum", nil) } - // Assign the first part to "peerID" and the second part to "dID" - peerID := parts[0] - dID := parts[1] - str, status, err := s.c.CheckQuorumStatus(peerID, dID) + + str, status, err := s.c.CheckQuorumStatus("", DID) if err != nil { s.log.Error("Quorum status check failed", "err", err) return s.BasicResponse(req, false, str, nil) diff --git a/server/config.go b/server/config.go index f4aa3c63..dfbc9156 100644 --- a/server/config.go +++ b/server/config.go @@ -1,6 +1,10 @@ package server import ( + "fmt" + "regexp" + "strings" + "github.com/rubixchain/rubixgoplatform/core" cc "github.com/rubixchain/rubixgoplatform/core/config" "github.com/rubixchain/rubixgoplatform/core/model" @@ -32,6 +36,16 @@ func (s *Server) APIAddBootStrap(req *ensweb.Request) *ensweb.Result { if err != nil { return s.BasicResponse(req, false, "invlid input request", nil) } + if len(m.Peers) == 0 { + s.log.Error("bootstrap Peers required to add") + return s.BasicResponse(req, false, "Bootstrap Peers required to add", nil) + } + for _, peer := range m.Peers { + if !strings.HasSuffix(peer, "/") { + s.log.Error(fmt.Sprintf("Invalid bootstrap peer : %s", peer)) + return s.BasicResponse(req, false, "Invalid bootstrap peer", nil) + } + } err = s.c.AddBootStrap(m.Peers) if err != nil { return s.BasicResponse(req, false, "Failed to add bootstrap peers, "+err.Error(), nil) @@ -46,6 +60,16 @@ func (s *Server) APIRemoveBootStrap(req *ensweb.Request) *ensweb.Result { if err != nil { return s.BasicResponse(req, false, "invlid input request", nil) } + if len(m.Peers) == 0 { + s.log.Error("Bootstrap peers required to remove") + return s.BasicResponse(req, false, "Bootstrap peers required to remove", nil) + } + for _, peer := range m.Peers { + if !strings.HasSuffix(peer, "/") { + s.log.Error(fmt.Sprintf("Invalid bootstrap peer : %s", peer)) + return s.BasicResponse(req, false, "Invalid bootstrap peer", nil) + } + } err = s.c.RemoveBootStrap(m.Peers) if err != nil { return s.BasicResponse(req, false, "Failed to remove bootstrap peers, "+err.Error(), nil) @@ -78,6 +102,17 @@ func (s *Server) APIAddQuorum(req *ensweb.Request) *ensweb.Result { if err != nil { return s.BasicResponse(req, false, "invlid input request", nil) } + if len(ql) < 5 { + s.log.Error("Length of Quorum list should be atleast 5") + return s.BasicResponse(req, false, "Length of Quorum list should be atleast 5", nil) + } + for _, q := range ql { + is_alphanumeric := regexp.MustCompile(`^[a-zA-Z0-9]*$`).MatchString(q.Address) + if !strings.HasPrefix(q.Address, "bafybmi") || len(q.Address) != 59 || !is_alphanumeric { + s.log.Error(fmt.Sprintf("Invalid quorum DID : %s", q.Address)) + return s.BasicResponse(req, false, fmt.Sprintf("Invalid quorum DID : %s", q.Address), nil) + } + } err = s.c.AddQuorum(ql) if err != nil { return s.BasicResponse(req, false, "Failed to add quorums, "+err.Error(), nil) @@ -132,6 +167,10 @@ func (s *Server) APIAddExplorer(req *ensweb.Request) *ensweb.Result { if err != nil { return s.BasicResponse(req, false, "invlid input request", nil) } + if len(m.Links) == 0 { + s.log.Error("explorer links required to add") + return s.BasicResponse(req, false, "explorer links required to add", nil) + } err = s.c.AddExplorer(m.Links) if err != nil { return s.BasicResponse(req, false, "failed to add explorer, "+err.Error(), nil) @@ -146,6 +185,10 @@ func (s *Server) APIRemoveExplorer(req *ensweb.Request) *ensweb.Result { if err != nil { return s.BasicResponse(req, false, "invlid input request", nil) } + if len(m.Links) == 0 { + s.log.Error("explorer links required to remove") + return s.BasicResponse(req, false, "explorer links required to remove", nil) + } err = s.c.RemoveExplorer(m.Links) if err != nil { return s.BasicResponse(req, false, "failed to remove explorer, "+err.Error(), nil) diff --git a/server/data_token.go b/server/data_token.go index 628ea69c..c27fe654 100644 --- a/server/data_token.go +++ b/server/data_token.go @@ -2,6 +2,8 @@ package server import ( "net/http" + "regexp" + "strings" "github.com/rubixchain/rubixgoplatform/core" "github.com/rubixchain/rubixgoplatform/core/model" @@ -26,6 +28,11 @@ func (s *Server) APICreateDataToken(req *ensweb.Request) *ensweb.Result { var dr core.DataTokenReq var err error dr.DID = s.GetQuerry(req, "did") + is_alphanumeric := regexp.MustCompile(`^[a-zA-Z0-9]*$`).MatchString(dr.DID) + if !strings.HasPrefix(dr.DID, "bafybmi") || len(dr.DID) != 59 || !is_alphanumeric { + s.log.Error("Invalid DID") + return s.BasicResponse(req, false, "Invalid DID", nil) + } dr.FolderName, err = s.c.CreateTempFolder() if err != nil { s.log.Error("failed to create folder", "err", err) @@ -59,6 +66,11 @@ func (s *Server) APICreateDataToken(req *ensweb.Request) *ensweb.Result { // @Router /api/commit-data-token [post] func (s *Server) APICommitDataToken(req *ensweb.Request) *ensweb.Result { did := s.GetQuerry(req, "did") + is_alphanumeric := regexp.MustCompile(`^[a-zA-Z0-9]*$`).MatchString(did) + if !strings.HasPrefix(did, "bafybmi") || len(did) != 59 || !is_alphanumeric { + s.log.Error("Invalid DID") + return s.BasicResponse(req, false, "Invalid DID", nil) + } batchID := s.GetQuerry(req, "batchID") if !s.validateDIDAccess(req, did) { return s.BasicResponse(req, false, "DID does not have an access", nil) @@ -97,6 +109,11 @@ func (s *Server) APIGetDataToken(req *ensweb.Request) *ensweb.Result { if did == "" { s.BasicResponse(req, false, "DID is required", nil) } + is_alphanumeric := regexp.MustCompile(`^[a-zA-Z0-9]*$`).MatchString(did) + if !strings.HasPrefix(did, "bafybmi") || len(did) != 59 || !is_alphanumeric { + s.log.Error("Invalid DID") + return s.BasicResponse(req, false, "Invalid DID", nil) + } dt := s.c.GetDataTokens(did) resp := model.DataTokenResponse{ BasicResponse: model.BasicResponse{ diff --git a/server/diagnostic.go b/server/diagnostic.go index cae75833..aacaec5c 100644 --- a/server/diagnostic.go +++ b/server/diagnostic.go @@ -2,6 +2,8 @@ package server import ( "net/http" + "regexp" + "strings" "github.com/rubixchain/rubixgoplatform/core/model" "github.com/rubixchain/rubixgoplatform/wrapper/ensweb" @@ -13,6 +15,11 @@ func (s *Server) APIDumpTokenChainBlock(req *ensweb.Request) *ensweb.Result { if err != nil { return s.BasicResponse(req, false, "Invalid input", nil) } + is_alphanumeric := regexp.MustCompile(`^[a-zA-Z0-9]*$`).MatchString(dr.Token) + if len(dr.Token) != 46 || !strings.HasPrefix(dr.Token, "Qm") || !is_alphanumeric { + s.log.Error("Invalid token") + return s.BasicResponse(req, false, "Invalid token", nil) + } drep := s.c.DumpTokenChain(&dr) return s.RenderJSON(req, drep, http.StatusOK) } @@ -23,6 +30,11 @@ func (s *Server) APIDumpSmartContractTokenChainBlock(req *ensweb.Request) *enswe if err != nil { return s.BasicResponse(req, false, "Invalid input", nil) } + is_alphanumeric := regexp.MustCompile(`^[a-zA-Z0-9]*$`).MatchString(dr.Token) + if len(dr.Token) != 46 || !strings.HasPrefix(dr.Token, "Qm") || !is_alphanumeric { + s.log.Error("Invalid smart contract token") + return s.BasicResponse(req, false, "Invalid smart contract token", nil) + } drep := s.c.DumpSmartContractTokenChain(&dr) return s.RenderJSON(req, drep, http.StatusOK) } diff --git a/server/did.go b/server/did.go index 777a2835..11ef9385 100644 --- a/server/did.go +++ b/server/did.go @@ -4,6 +4,7 @@ import ( "encoding/json" "net/http" "os" + "regexp" "strings" "time" @@ -61,6 +62,11 @@ func (s *Server) APICreateDID(req *ensweb.Request) *ensweb.Result { return s.BasicResponse(req, false, "failed to parse did configuration", nil) } + if didCreate.Type < 0 || didCreate.Type > 4 { + s.log.Error("DID Type should be between 0 and 4") + return s.BasicResponse(req, false, "DID Type should be between 0 and 4", nil) + } + for _, fileName := range fileNames { if strings.Contains(fileName, did.PubKeyFileName) { @@ -172,6 +178,11 @@ func (s *Server) APIRegisterDID(req *ensweb.Request) *ensweb.Result { if !ok { return s.BasicResponse(req, false, "Failed to parse input", nil) } + is_alphanumeric := regexp.MustCompile(`^[a-zA-Z0-9]*$`).MatchString(didStr) + if !strings.HasPrefix(didStr, "bafybmi") || len(didStr) != 59 || !is_alphanumeric { + s.log.Error("Invalid DID") + return s.BasicResponse(req, false, "Invalid DID", nil) + } s.c.AddWebReq(req) go s.c.RegisterDID(req.ID, didStr) @@ -202,6 +213,11 @@ func (s *Server) APISetupDID(req *ensweb.Request) *ensweb.Result { return s.BasicResponse(req, false, "failed to parse did configuration", nil) } + if didCreate.Type < 0 || didCreate.Type > 4 { + s.log.Error("DID Type should be between 0 and 4") + return s.BasicResponse(req, false, "DID Type should be between 0 and 4", nil) + } + for _, fileName := range fileNames { if strings.Contains(fileName, did.PvtKeyFileName) { diff --git a/server/migration.go b/server/migration.go index 682d8eaa..2844669b 100644 --- a/server/migration.go +++ b/server/migration.go @@ -14,6 +14,10 @@ func (s *Server) APIMigrateNode(req *ensweb.Request) *ensweb.Result { if err != nil { return s.BasicResponse(req, false, "Failed to parse input", nil) } + if m.DIDType < 0 || m.DIDType > 4 { + s.log.Error("DID Type should be between 0 and 4") + return s.BasicResponse(req, false, "DID Type should be between 0 and 4", nil) + } didDir := DIDRootDir if s.cfg.EnableAuth { // always expect client tokne to present diff --git a/server/quorum.go b/server/quorum.go index 48316a5f..34a4c02b 100644 --- a/server/quorum.go +++ b/server/quorum.go @@ -1,6 +1,9 @@ package server import ( + "regexp" + "strings" + "github.com/rubixchain/rubixgoplatform/core/model" "github.com/rubixchain/rubixgoplatform/wrapper/ensweb" ) @@ -11,6 +14,11 @@ func (s *Server) APISetupQuorum(req *ensweb.Request) *ensweb.Result { if err != nil { return s.BasicResponse(req, false, "Failed to parse the input", nil) } + is_alphanumeric := regexp.MustCompile(`^[a-zA-Z0-9]*$`).MatchString(qs.DID) + if !strings.HasPrefix(qs.DID, "bafybmi") || len(qs.DID) != 59 || !is_alphanumeric { + s.log.Error("Invalid DID") + return s.BasicResponse(req, false, "Invalid DID", nil) + } err = s.c.SetupQuorum(qs.DID, qs.Password, qs.PrivKeyPassword) if err != nil { return s.BasicResponse(req, false, "Failed to setup quorum, "+err.Error(), nil) diff --git a/server/smart_contract.go b/server/smart_contract.go index 755cb147..b4c531e2 100644 --- a/server/smart_contract.go +++ b/server/smart_contract.go @@ -5,6 +5,8 @@ import ( "io" "os" "path/filepath" + "regexp" + "strings" "github.com/rubixchain/rubixgoplatform/core" "github.com/rubixchain/rubixgoplatform/core/model" @@ -51,10 +53,31 @@ func (s *Server) APIDeploySmartContract(req *ensweb.Request) *ensweb.Result { if err != nil { return s.BasicResponse(req, false, "Invalid input", nil) } + is_alphanumeric := regexp.MustCompile(`^[a-zA-Z0-9]*$`).MatchString(deployReq.SmartContractToken) + if len(deployReq.SmartContractToken) != 46 || !strings.HasPrefix(deployReq.SmartContractToken, "Qm") || !is_alphanumeric { + s.log.Error("Invalid smart contract token") + return s.BasicResponse(req, false, "Invalid smart contract token", nil) + } _, did, ok := util.ParseAddress(deployReq.DeployerAddress) if !ok { return s.BasicResponse(req, false, "Invalid Deployer address", nil) } + + is_alphanumeric = regexp.MustCompile(`^[a-zA-Z0-9]*$`).MatchString(did) + if !strings.HasPrefix(did, "bafybmi") || len(did) != 59 || !is_alphanumeric { + s.log.Error("Invalid deployer DID") + return s.BasicResponse(req, false, "Invalid input", nil) + } + + if deployReq.RBTAmount < 0.00001 { + s.log.Error("Invalid RBT amount. Minimum RBT amount should be 0.00001") + return s.BasicResponse(req, false, "Invalid RBT amount. Minimum RBT amount should be 0.00001", nil) + } + if deployReq.QuorumType < 1 || deployReq.QuorumType > 2 { + s.log.Error("Invalid quorum type") + return s.BasicResponse(req, false, "Invalid quorum type", nil) + } + if !s.validateDIDAccess(req, did) { return s.BasicResponse(req, false, "DID does not have an access", nil) } @@ -184,6 +207,12 @@ func (s *Server) APIGenerateSmartContract(req *ensweb.Request) *ensweb.Result { deploySC.DID = did["did"][0] + is_alphanumeric := regexp.MustCompile(`^[a-zA-Z0-9]*$`).MatchString(deploySC.DID) + if !strings.HasPrefix(deploySC.DID, "bafybmi") || len(deploySC.DID) != 59 || !is_alphanumeric { + s.log.Error("Invalid DID") + return s.BasicResponse(req, false, "Invalid DID", nil) + } + if !s.validateDIDAccess(req, deploySC.DID) { return s.BasicResponse(req, false, "Ensure you enter the correct DID", nil) } @@ -267,6 +296,13 @@ func (s *Server) APIFetchSmartContract(req *ensweb.Request) *ensweb.Result { s.log.Error("Fetch smart contract failed, failed to fetch smartcontract token value", "err", err) return s.BasicResponse(req, false, "Fetch smart contract failed, failed to fetch smartcontract token value", nil) } + + is_alphanumeric := regexp.MustCompile(`^[a-zA-Z0-9]*$`).MatchString(fetchSC.SmartContractToken) + if len(fetchSC.SmartContractToken) != 46 || !strings.HasPrefix(fetchSC.SmartContractToken, "Qm") || !is_alphanumeric { + s.log.Error("Invalid smart contract token") + return s.BasicResponse(req, false, "Invalid smart contract token", nil) + } + fetchSC.SmartContractTokenPath, err = s.c.RenameSCFolder(fetchSC.SmartContractTokenPath, fetchSC.SmartContractToken) if err != nil { s.log.Error("Fetch smart contract failed, failed to create SC folder", "err", err) @@ -291,6 +327,23 @@ func (s *Server) APIPublishContract(request *ensweb.Request) *ensweb.Result { return s.BasicResponse(request, false, "Failed to parse input", nil) } + is_alphanumeric := regexp.MustCompile(`^[a-zA-Z0-9]*$`).MatchString(newEvent.SmartContractToken) + + if len(newEvent.SmartContractToken) != 46 || !strings.HasPrefix(newEvent.SmartContractToken, "Qm") || !is_alphanumeric { + s.log.Error("Invalid smart contract token") + return s.BasicResponse(request, false, "Invalid smart contract token", nil) + } + + is_alphanumeric = regexp.MustCompile(`^[a-zA-Z0-9]*$`).MatchString(newEvent.Did) + if !strings.HasPrefix(newEvent.Did, "bafybmi") || len(newEvent.Did) != 59 || !is_alphanumeric { + s.log.Error("Invalid DID") + return s.BasicResponse(request, false, "Invalid DID", nil) + } + if newEvent.Type < 1 || newEvent.Type > 2 { + s.log.Error("Invalid publish type") + return s.BasicResponse(request, false, "Invalid publish type", nil) + } + go s.c.PublishNewEvent(&newEvent) return s.BasicResponse(request, true, "Smart contract published successfully", nil) } @@ -310,6 +363,11 @@ func (s *Server) APISubscribecontract(request *ensweb.Request) *ensweb.Result { if err != nil { return s.BasicResponse(request, false, "Failed to parse input", nil) } + is_alphanumeric := regexp.MustCompile(`^[a-zA-Z0-9]*$`).MatchString(newSubscription.SmartContractToken) + if len(newSubscription.SmartContractToken) != 46 || !strings.HasPrefix(newSubscription.SmartContractToken, "Qm") || !is_alphanumeric { + s.log.Error("Invalid smart contract token") + return s.BasicResponse(request, false, "Invalid smart contract token", nil) + } topic := newSubscription.SmartContractToken s.c.AddWebReq(request) go s.c.SubsribeContractSetup(request.ID, topic) @@ -341,7 +399,23 @@ func (s *Server) APIExecuteSmartContract(req *ensweb.Request) *ensweb.Result { } _, did, ok := util.ParseAddress(executeReq.ExecutorAddress) if !ok { - return s.BasicResponse(req, false, "Invalid Deployer address", nil) + return s.BasicResponse(req, false, "Invalid Executer address", nil) + } + + is_alphanumeric := regexp.MustCompile(`^[a-zA-Z0-9]*$`).MatchString(executeReq.SmartContractToken) + if len(executeReq.SmartContractToken) != 46 || !strings.HasPrefix(executeReq.SmartContractToken, "Qm") || !is_alphanumeric { + s.log.Error("Invalid smart contract token") + return s.BasicResponse(req, false, "Invalid smart contract token", nil) + } + + is_alphanumeric = regexp.MustCompile(`^[a-zA-Z0-9]*$`).MatchString(executeReq.ExecutorAddress) + if !strings.HasPrefix(executeReq.ExecutorAddress, "bafybmi") || len(executeReq.ExecutorAddress) != 59 || !is_alphanumeric { + s.log.Error("Invalid executer DID") + return s.BasicResponse(req, false, "Invalid executer DID", nil) + } + if executeReq.QuorumType < 1 || executeReq.QuorumType > 2 { + s.log.Error("Invalid quorum type") + return s.BasicResponse(req, false, "Invalid quorum type", nil) } if !s.validateDIDAccess(req, did) { return s.BasicResponse(req, false, "DID does not have an access", nil) diff --git a/server/tokens.go b/server/tokens.go index 5db737c4..e718bb59 100644 --- a/server/tokens.go +++ b/server/tokens.go @@ -2,6 +2,8 @@ package server import ( "net/http" + "regexp" + "strings" "github.com/rubixchain/rubixgoplatform/core/model" "github.com/rubixchain/rubixgoplatform/did" @@ -12,6 +14,11 @@ import ( func (s *Server) APIGetAllTokens(req *ensweb.Request) *ensweb.Result { tokenType := s.GetQuerry(req, "type") did := s.GetQuerry(req, "did") + is_alphanumeric := regexp.MustCompile(`^[a-zA-Z0-9]*$`).MatchString(did) + if !strings.HasPrefix(did, "bafybmi") || len(did) != 59 || !is_alphanumeric { + s.log.Error("Invalid DID") + return s.BasicResponse(req, false, "Invalid DID", nil) + } tr, err := s.c.GetAllTokens(did, tokenType) if err != nil { return s.BasicResponse(req, false, "Failed to get tokens", nil) @@ -25,6 +32,16 @@ func (s *Server) APIGenerateTestToken(req *ensweb.Request) *ensweb.Result { if err != nil { return s.BasicResponse(req, false, "Invalid input", nil) } + is_alphanumeric := regexp.MustCompile(`^[a-zA-Z0-9]*$`).MatchString(tr.DID) + if !strings.HasPrefix(tr.DID, "bafybmi") || len(tr.DID) != 59 || !is_alphanumeric { + s.log.Error("Invalid DID") + return s.BasicResponse(req, false, "Invalid DID", nil) + } + if tr.NumberOfTokens <= 0 { + s.log.Error("Invalid RBT amount, tokens generated should be a whole number and greater than 0") + return s.BasicResponse(req, false, "Invalid RBT amount, tokens generated should be a whole number and greater than 0", nil) + } + if !s.validateDIDAccess(req, tr.DID) { return s.BasicResponse(req, false, "DID does not have an access", nil) } @@ -62,6 +79,24 @@ func (s *Server) APIInitiateRBTTransfer(req *ensweb.Request) *ensweb.Result { if !ok { return s.BasicResponse(req, false, "Invalid sender address", nil) } + is_alphanumeric_sender := regexp.MustCompile(`^[a-zA-Z0-9]*$`).MatchString(rbtReq.Sender) + is_alphanumeric_receiver := regexp.MustCompile(`^[a-zA-Z0-9]*$`).MatchString(rbtReq.Receiver) + if !is_alphanumeric_sender || !is_alphanumeric_receiver { + s.log.Error("Invalid sender or receiver address. Please provide valid DID") + return s.BasicResponse(req, false, "Invalid sender or receiver address", nil) + } + if !strings.HasPrefix(did, "bafybmi") || len(did) != 59 || !strings.HasPrefix(rbtReq.Receiver, "bafybmi") || len(rbtReq.Receiver) != 59 { + s.log.Error("Invalid sender or receiver DID") + return s.BasicResponse(req, false, "Invalid sender or receiver DID", nil) + } + if rbtReq.TokenCount < 0.00001 { + s.log.Error("Invalid RBT amount. RBT amount should be atlease 0.00001") + return s.BasicResponse(req, false, "Invalid RBT amount. RBT amount should be atlease 0.00001", nil) + } + if rbtReq.Type < 1 || rbtReq.Type > 2 { + s.log.Error("Invalid trans type. TransType should be 1 or 2") + return s.BasicResponse(req, false, "Invalid trans type. TransType should be 1 or 2", nil) + } if !s.validateDIDAccess(req, did) { return s.BasicResponse(req, false, "DID does not have an access", nil) } @@ -84,6 +119,12 @@ func (s *Server) APIGetAccountInfo(req *ensweb.Request) *ensweb.Result { if !s.validateDIDAccess(req, did) { return s.BasicResponse(req, false, "DID does not have an access", nil) } + + is_alphanumeric := regexp.MustCompile(`^[a-zA-Z0-9]*$`).MatchString(did) + if !strings.HasPrefix(did, "bafybmi") || len(did) != 59 || !is_alphanumeric { + s.log.Error("Invalid DID") + return s.BasicResponse(req, false, "Invalid DID", nil) + } info, err := s.c.GetAccountInfo(did) if err != nil { return s.BasicResponse(req, false, err.Error(), nil) diff --git a/server/txndetails.go b/server/txndetails.go index c4397c90..fe43a9b4 100644 --- a/server/txndetails.go +++ b/server/txndetails.go @@ -2,6 +2,8 @@ package server import ( "net/http" + "regexp" + "strings" "github.com/rubixchain/rubixgoplatform/core/model" "github.com/rubixchain/rubixgoplatform/core/wallet" @@ -69,6 +71,11 @@ func (s *Server) APIGetTxnByTxnID(req *ensweb.Request) *ensweb.Result { // @Router /api/get-by-did [get] func (s *Server) APIGetTxnByDID(req *ensweb.Request) *ensweb.Result { did := s.GetQuerry(req, "DID") + is_alphanumeric := regexp.MustCompile(`^[a-zA-Z0-9]*$`).MatchString(did) + if !strings.HasPrefix(did, "bafybmi") || len(did) != 59 || !is_alphanumeric { + s.log.Error("Invalid DID") + return s.BasicResponse(req, false, "Invalid DID", nil) + } role := s.GetQuerry(req, "Role") startDate := s.GetQuerry(req, "StartDate") endDate := s.GetQuerry(req, "EndDate") From 9ff1a40f74a130b2be282b0057adc2f278712eb6 Mon Sep 17 00:00:00 2001 From: Vaishnav CH Date: Wed, 10 Jul 2024 19:03:14 +0530 Subject: [PATCH 086/129] remove delay in transfer finality when quorum have insufficient balance. --- core/core.go | 78 ++++++++++++++++++++-------------------- core/quorum_initiator.go | 36 ++++++++++++++----- core/quorum_recv.go | 12 +++++++ core/transfer.go | 4 +++ 4 files changed, 83 insertions(+), 47 deletions(-) diff --git a/core/core.go b/core/core.go index b5f0ac54..cac270ad 100644 --- a/core/core.go +++ b/core/core.go @@ -73,44 +73,46 @@ const ( ) type Core struct { - cfg *config.Config - cfgFile string - encKey string - log logger.Logger - peerID string - lock sync.RWMutex - ipfsLock sync.RWMutex - qlock sync.RWMutex - rlock sync.Mutex - ipfs *ipfsnode.Shell - ipfsState bool - ipfsChan chan bool - d *did.DID - up *unpledge.UnPledge - didDir string - pm *ipfsport.PeerManager - qm *QuorumManager - l *ipfsport.Listener - ps *pubsub.PubSub - started bool - ipfsApp string - testNet bool - testNetKey string - version string - quorumRequest map[string]*ConsensusStatus - pd map[string]*PledgeDetails - webReq map[string]*did.DIDChan - w *wallet.Wallet - qc map[string]did.DIDCrypto - pqc map[string]did.DIDCrypto - sd map[string]*ServiceDetials - s storage.Storage - as storage.Storage - srv *service.Service - arbitaryMode bool - arbitaryAddr []string - ec *ExplorerClient - secret []byte + cfg *config.Config + cfgFile string + encKey string + log logger.Logger + peerID string + lock sync.RWMutex + ipfsLock sync.RWMutex + qlock sync.RWMutex + rlock sync.Mutex + ipfs *ipfsnode.Shell + ipfsState bool + ipfsChan chan bool + d *did.DID + up *unpledge.UnPledge + didDir string + pm *ipfsport.PeerManager + qm *QuorumManager + l *ipfsport.Listener + ps *pubsub.PubSub + started bool + ipfsApp string + testNet bool + testNetKey string + version string + quorumRequest map[string]*ConsensusStatus + pd map[string]*PledgeDetails + webReq map[string]*did.DIDChan + w *wallet.Wallet + qc map[string]did.DIDCrypto + pqc map[string]did.DIDCrypto + sd map[string]*ServiceDetials + s storage.Storage + as storage.Storage + srv *service.Service + arbitaryMode bool + arbitaryAddr []string + ec *ExplorerClient + secret []byte + quorumCount int + noBalanceQuorumCount int } func InitConfig(configFile string, encKey string, node uint16) error { diff --git a/core/quorum_initiator.go b/core/quorum_initiator.go index 71497523..1d1fab30 100644 --- a/core/quorum_initiator.go +++ b/core/quorum_initiator.go @@ -363,6 +363,8 @@ func (c *Core) initiateConsensus(cr *ConensusRequest, sc *contract.Contract, dc delete(c.pd, cr.ReqID) c.qlock.Unlock() }() + c.quorumCount = 0 + c.noBalanceQuorumCount = 0 for _, a := range cr.QuorumList { //This part of code is trying to connect to the quorums in quorum list, where various functions are called to pledge the tokens //and checking of transaction by the quorum i.e. consensus for the transaction. Once the quorum is connected, it pledges and @@ -805,6 +807,11 @@ func (c *Core) connectQuorum(cr *ConensusRequest, addr string, qt int, sc *contr } err = c.initPledgeQuorumToken(cr, p, qt) if err != nil { + if strings.Contains(err.Error(), "don't have enough balance to pledge") { + c.log.Error("Quorum failed to pledge token") + c.finishConsensus(cr.ReqID, qt, p, false, "", nil, nil) + return + } c.log.Error("Failed to pledge token", "err", err) c.finishConsensus(cr.ReqID, qt, p, false, "", nil, nil) return @@ -1179,10 +1186,6 @@ func (c *Core) initPledgeQuorumToken(cr *ConensusRequest, p *ipfsport.Peer, qt i pr := PledgeRequest{ TokensRequired: CeilfloatPrecision(pledgeTokensPerQuorum, MaxDecimalPlaces), // Request the determined number of tokens per quorum, } - // l := len(pd.PledgedTokens) - // for i := pd.NumPledgedTokens; i < l; i++ { - // pr.Tokens = append(pr.Tokens, cr.WholeTokens[i]) - // } var prs PledgeReply err := p.SendJSONRequest("POST", APIReqPledgeToken, nil, &pr, &prs, true) if err != nil { @@ -1191,7 +1194,16 @@ func (c *Core) initPledgeQuorumToken(cr *ConensusRequest, p *ipfsport.Peer, qt i cs.PledgeLock.Unlock() return err } + if strings.Contains(prs.Message, "Quorum don't have enough balance to pledge") { + c.quorumCount++ + c.noBalanceQuorumCount++ + cs.PledgeLock.Unlock() + did := p.GetPeerDID() + c.log.Error("Quorum (DID:" + did + ") don't have enough balance to pledge") + return fmt.Errorf("Quorum (DID:" + did + ") don't have enough balance to pledge") + } if prs.Status { + c.quorumCount++ did := p.GetPeerDID() pd.PledgedTokens[did] = make([]string, 0) for i, t := range prs.Tokens { @@ -1223,12 +1235,18 @@ func (c *Core) initPledgeQuorumToken(cr *ConensusRequest, p *ipfsport.Peer, qt i err := fmt.Errorf("invalid pledge request") return err } - if pd.RemPledgeTokens <= 0 { + if pd.RemPledgeTokens > 0 { + if c.quorumCount < QuorumRequired { + if count == 300 { + err := fmt.Errorf("Unable to pledge after wait") + return err + } + } else if c.quorumCount == QuorumRequired { + err := fmt.Errorf("Unable to pledge") + return err + } + } else if pd.RemPledgeTokens <= 0 { return nil - } else if count == 300 { - c.log.Error("Unable to pledge token") - err := fmt.Errorf("unable to pledge token") - return err } } } diff --git a/core/quorum_recv.go b/core/quorum_recv.go index fb621dcb..43d8110e 100644 --- a/core/quorum_recv.go +++ b/core/quorum_recv.go @@ -578,6 +578,18 @@ func (c *Core) reqPledgeToken(req *ensweb.Request) *ensweb.Result { return c.l.RenderJSON(req, &crep, http.StatusOK) } + var availableBalance model.DIDAccountInfo + availableBalance, err = c.GetAccountInfo(did) + if err != nil { + c.log.Error("Unable to check quorum balance") + } + availableRBT := availableBalance.RBTAmount + if availableRBT < pr.TokensRequired { + c.log.Error("Quorum don't have enough balance to pledge") + crep.Message = "Quorum don't have enough balance to pledge" + return c.l.RenderJSON(req, &crep, http.StatusOK) + } + if (pr.TokensRequired) < MinDecimalValue(MaxDecimalPlaces) { c.log.Error("Pledge amount is less than ", MinDecimalValue(MaxDecimalPlaces)) crep.Message = "Pledge amount is less than minimum transcation amount" diff --git a/core/transfer.go b/core/transfer.go index c7ef3e20..55bb2fdc 100644 --- a/core/transfer.go +++ b/core/transfer.go @@ -198,6 +198,10 @@ func (c *Core) initiateRBTTransfer(reqID string, req *model.RBTTransferRequest) } td, _, err := c.initiateConsensus(cr, sc, dc) if err != nil { + if c.noBalanceQuorumCount > 2 { + resp.Message = "Consensus failed due to insufficient balance in Quorum, Retry transaction after sometime" + return resp + } c.log.Error("Consensus failed ", "err", err) resp.Message = "Consensus failed " + err.Error() return resp From afabefe785159ee9786846b16a3e077f1b4133ab Mon Sep 17 00:00:00 2001 From: Vaishnav CH Date: Thu, 11 Jul 2024 11:43:38 +0530 Subject: [PATCH 087/129] Add typoerror fix --- core/transfer.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/transfer.go b/core/transfer.go index 55bb2fdc..de8cb337 100644 --- a/core/transfer.go +++ b/core/transfer.go @@ -199,7 +199,7 @@ func (c *Core) initiateRBTTransfer(reqID string, req *model.RBTTransferRequest) td, _, err := c.initiateConsensus(cr, sc, dc) if err != nil { if c.noBalanceQuorumCount > 2 { - resp.Message = "Consensus failed due to insufficient balance in Quorum, Retry transaction after sometime" + resp.Message = "Consensus failed due to insufficient balance in Quorum(s), Retry transaction after sometime" return resp } c.log.Error("Consensus failed ", "err", err) From f2696435f2e84d16ff29432be891be4cc88dc73c Mon Sep 17 00:00:00 2001 From: Arnab Ghose Date: Thu, 11 Jul 2024 18:22:02 +0530 Subject: [PATCH 088/129] feat: periodic pledging implementation --- README.md | 25 ++ block/block.go | 10 + client/token.go | 24 ++ client/transfer.go | 10 + client/unpledge.go | 16 + command/command.go | 22 +- command/tokenstate.go | 37 ++ command/transfer.go | 22 ++ command/unpledge.go | 11 + contract/contract.go | 2 +- contract/pledge.go | 2 +- core/core.go | 11 +- core/data_token.go | 9 +- core/model/data_token.go | 10 +- core/model/quorum.go | 21 + core/model/tokens.go | 15 +- core/model/txndetails.go | 30 +- core/nft.go | 2 +- core/quorum_initiator.go | 375 ++++++++++++++++-- core/quorum_recv.go | 494 +++++++++++------------- core/quorum_validation.go | 2 + core/self_transfer.go | 250 ++++++++++++ core/smart_contract_token_operations.go | 10 +- core/token.go | 44 ++- core/transfer.go | 295 +++++++++----- core/txndetails.go | 20 +- core/unpledge.go | 440 +++++++++++++++++---- core/unpledge/Difficultlevel.go | 10 - core/unpledge/unpledge.go | 358 +++-------------- core/wallet/credit.go | 3 + core/wallet/data_token.go | 28 +- core/wallet/token.go | 142 ++++++- core/wallet/token_chain.go | 7 + core/wallet/transaction_history.go | 47 +-- core/wallet/wallet.go | 12 +- docs/docs.go | 173 ++++++++- docs/swagger.json | 173 ++++++++- docs/swagger.yaml | 116 +++++- grpcserver/token.go | 2 +- server/self_transfer.go | 39 ++ server/server.go | 4 + server/tokens.go | 58 +++ server/txndetails.go | 21 +- server/unpledge.go | 35 ++ setup/setup.go | 4 + tests/node/actions.py | 4 +- tests/run.py | 39 +- 47 files changed, 2514 insertions(+), 970 deletions(-) create mode 100644 client/unpledge.go create mode 100644 command/tokenstate.go create mode 100644 command/unpledge.go create mode 100644 core/self_transfer.go delete mode 100644 core/unpledge/Difficultlevel.go create mode 100644 server/self_transfer.go create mode 100644 server/unpledge.go diff --git a/README.md b/README.md index 34ca4965..6aa65b90 100644 --- a/README.md +++ b/README.md @@ -367,4 +367,29 @@ This following options are used for this command -didType int DID type (0-Basic Mode, 1-Standard Mode, 2-Wallet Mode, 3-Child Mode, 4-Light Mode) (default 0) +``` + +To check details about the token states for which pledging has been done +: To check for what token states the pledging has been done, and which tokens are pledged + +``` +./rubixgoplatform getpledgedtokendetails + +This following options are used for this command + -port string + Server/Host port (default "20000") +``` + +To check tokenstatehash status +: To check if a particular tokenstatehash is exhausted, i.e if it has been transferred further + +``` +./rubixgoplatform tokenstatehash + +This following options are used for this command + -port string + Server/Host port (default "20000") + + -tokenstatehash string + TokenState Hash, for which the status needs to be checked ``` \ No newline at end of file diff --git a/block/block.go b/block/block.go index 074e3bcd..2f40761b 100644 --- a/block/block.go +++ b/block/block.go @@ -41,6 +41,7 @@ const ( TCTokenValueKey string = "10" TCChildTokensKey string = "11" TCSenderSignatureKey string = "12" + TCEpochKey string = "epoch" ) const ( @@ -69,6 +70,7 @@ type TokenChainBlock struct { TokenValue float64 `json:"tokenValue"` ChildTokens []string `json:"childTokens"` SenderSignature *SenderSignature `json:"senderSignature"` + Epoch int `json:"epoch"` } type PledgeDetail struct { @@ -183,6 +185,10 @@ func CreateNewBlock(ctcb map[string]*Block, tcb *TokenChainBlock) *Block { ntcb[TCChildTokensKey] = tcb.ChildTokens } + if tcb.Epoch != 0 { + ntcb[TCEpochKey] = tcb.Epoch + } + blk := InitBlock(nil, ntcb) return blk } @@ -710,3 +716,7 @@ func (b *Block) GetTokenValue() float64 { func (b *Block) GetChildTokens() []string { return util.GetStringSliceFromMap(b.bm, TCChildTokensKey) } + +func (b *Block) GetEpoch() int64 { + return int64(util.GetIntFromMap(b.bm, TCEpochKey)) +} diff --git a/client/token.go b/client/token.go index d5c56bec..0c6a4b29 100644 --- a/client/token.go +++ b/client/token.go @@ -1,6 +1,8 @@ package client import ( + "time" + "github.com/rubixchain/rubixgoplatform/core/model" "github.com/rubixchain/rubixgoplatform/setup" ) @@ -29,3 +31,25 @@ func (c *Client) GetAllTokens(didStr string, tokenType string) (*model.TokenResp } return &tr, nil } + +func (c *Client) GetPledgedTokenDetails() (*model.TokenStateResponse, error) { + var tr model.TokenStateResponse + err := c.sendJSONRequest("GET", setup.APIGetPledgedTokenDetails, nil, nil, &tr, time.Minute*2) + if err != nil { + c.log.Error("Failed to get pledged token details", "err", err) + return nil, err + } + return &tr, nil +} + +func (c *Client) GetPinnedInfo(TokenStateHash string) (*model.BasicResponse, error) { + m := make(map[string]string) + m["tokenstatehash"] = TokenStateHash + var br model.BasicResponse + err := c.sendJSONRequest("DELETE", setup.APICheckPinnedState, m, nil, &br, time.Minute*2) + if err != nil { + c.log.Error("Failed to get Pins", "err", err) + return nil, err + } + return &br, nil +} diff --git a/client/transfer.go b/client/transfer.go index c65ef871..0449bb54 100644 --- a/client/transfer.go +++ b/client/transfer.go @@ -16,3 +16,13 @@ func (c *Client) TransferRBT(rt *model.RBTTransferRequest) (*model.BasicResponse } return &br, nil } + +func (c *Client) SelfTransferRBT(rt *model.RBTTransferRequest) (*model.BasicResponse, error) { + var br model.BasicResponse + err := c.sendJSONRequest("POST", setup.APISelfTransfer, nil, rt, &br, time.Minute*2) + if err != nil { + c.log.Error("Failed RBT Transfer", "err", err) + return nil, err + } + return &br, nil +} diff --git a/client/unpledge.go b/client/unpledge.go new file mode 100644 index 00000000..aababe4e --- /dev/null +++ b/client/unpledge.go @@ -0,0 +1,16 @@ +package client + +import ( + "github.com/rubixchain/rubixgoplatform/core/model" + "github.com/rubixchain/rubixgoplatform/setup" +) + +func (c *Client) RunUnpledge() (string, bool) { + var resp model.BasicResponse + err := c.sendJSONRequest("POST", setup.APIRunUnpledge, nil, struct{}{}, &resp) + if err != nil { + return err.Error(), false + } + + return resp.Message, resp.Status +} diff --git a/command/command.go b/command/command.go index bef52bad..c77fe0fc 100644 --- a/command/command.go +++ b/command/command.go @@ -83,6 +83,10 @@ const ( RemoveExplorerCmd string = "removeexplorer" GetAllExplorerCmd string = "getallexplorer" AddPeerDetailsCmd string = "addpeerdetails" + GetPledgedTokenDetailsCmd string = "getpledgedtokendetails" + CheckPinnedState string = "checkpinnedstate" + SelfTransferRBT string = "self-transfer-rbt" + RunUnpledge string = "run-unpledge" ) var commands = []string{VersionCmd, @@ -129,7 +133,10 @@ var commands = []string{VersionCmd, GetSmartContractData, GetPeerID, AddPeerDetailsCmd, + SelfTransferRBT, + RunUnpledge, } + var commandsHelp = []string{"To get tool version", "To get help", "To run the rubix core", @@ -173,7 +180,10 @@ var commandsHelp = []string{"To get tool version", "This command gets token block", "This command gets the smartcontract data from latest block", "This command will fetch the peer ID of the node", - "This command is to add the peer details manually"} + "This command is to add the peer details manually", + "This command will initiate a self RBT transfer", + "This command will unpledge all the pledged tokens", +} type Command struct { cfg config.Config @@ -251,6 +261,7 @@ type Command struct { links []string mnemonicFile string ChildPath int + TokenState string } func showVersion() { @@ -447,6 +458,7 @@ func Run(args []string) { flag.BoolVar(&cmd.latest, "latest", false, "flag to set latest") flag.StringVar(&cmd.quorumAddr, "quorumAddr", "", "Quorum Node Address to check the status of the Quorum") flag.StringVar(&links, "links", "", "Explorer url") + flag.StringVar(&cmd.TokenState, "tokenstatehash", "", "Give Token State Hash to check state") if len(os.Args) < 2 { fmt.Println("Invalid Command") @@ -606,6 +618,14 @@ func Run(args []string) { cmd.getAllExplorer() case AddPeerDetailsCmd: cmd.AddPeerDetails() + case GetPledgedTokenDetailsCmd: + cmd.GetPledgedTokenDetails() + case CheckPinnedState: + cmd.CheckPinnedState() + case SelfTransferRBT: + cmd.SelfTransferRBT() + case RunUnpledge: + cmd.RunUnpledge() default: cmd.log.Error("Invalid command") } diff --git a/command/tokenstate.go b/command/tokenstate.go new file mode 100644 index 00000000..d56a3e0b --- /dev/null +++ b/command/tokenstate.go @@ -0,0 +1,37 @@ +package command + +import "fmt" + +func (cmd *Command) GetPledgedTokenDetails() { + info, err := cmd.c.GetPledgedTokenDetails() + if err != nil { + cmd.log.Error("Invalid response from the node", "err", err) + return + } + fmt.Printf("Response : %v\n", info) + if !info.Status { + cmd.log.Error("Failed to get account info", "message", info.Message) + } else { + cmd.log.Info("Successfully got the pledged token states info") + fmt.Println("DID ", "Pledged Token ", "Token State") + for _, i := range info.PledgedTokenStateDetails { + fmt.Println(i.DID, " ", i.TokensPledged, " ", i.TokenStateHash) + } + } +} + +//command will take token hash, check for ipfs pinning, if no, ignore, if yes, get token detail, unpledge. + +func (cmd *Command) CheckPinnedState() { + info, err := cmd.c.GetPinnedInfo(cmd.TokenState) + if err != nil { + cmd.log.Error("Invalid response from the node", "err", err) + return + } + fmt.Printf("Response : %v\n", info) + if !info.Status { + cmd.log.Debug("Pin not available", "message", info.Message) + } else { + cmd.log.Info("Token State is Pinned") + } +} diff --git a/command/transfer.go b/command/transfer.go index 46c28f8c..6e689da1 100644 --- a/command/transfer.go +++ b/command/transfer.go @@ -26,3 +26,25 @@ func (cmd *Command) TransferRBT() { cmd.log.Info(msg) cmd.log.Info("RBT transfered successfully") } + + +func (cmd *Command) SelfTransferRBT() { + rt := model.RBTTransferRequest{ + Sender: cmd.senderAddr, + Receiver: cmd.senderAddr, + Type: cmd.transType, + } + + br, err := cmd.c.TransferRBT(&rt) + if err != nil { + cmd.log.Error("Failed to self RBT transfer", "err", err) + return + } + msg, status := cmd.SignatureResponse(br) + if !status { + cmd.log.Error("Failed to self transfer RBT", "msg", msg) + return + } + cmd.log.Info(msg) + cmd.log.Info("Self RBT transfer successful") +} \ No newline at end of file diff --git a/command/unpledge.go b/command/unpledge.go new file mode 100644 index 00000000..c74c7c15 --- /dev/null +++ b/command/unpledge.go @@ -0,0 +1,11 @@ +package command + +func (cmd *Command) RunUnpledge() { + msg, status := cmd.c.RunUnpledge() + if !status { + cmd.log.Error(msg) + return + } + + cmd.log.Debug(msg) +} \ No newline at end of file diff --git a/contract/contract.go b/contract/contract.go index d19334e3..ed1779d4 100644 --- a/contract/contract.go +++ b/contract/contract.go @@ -265,7 +265,7 @@ func (c *Contract) GetPledgeMode() int { mi, ok := c.sm[SCPledgeModeKey] // Default mode is POW if !ok { - return POWPledgeMode + return PeriodicPledgeMode } return mi.(int) } diff --git a/contract/pledge.go b/contract/pledge.go index fd918c78..edc0dd76 100644 --- a/contract/pledge.go +++ b/contract/pledge.go @@ -1,6 +1,6 @@ package contract const ( - POWPledgeMode int = iota + PeriodicPledgeMode int = iota NoPledgeMode ) diff --git a/core/core.go b/core/core.go index 0a78001a..80acc708 100644 --- a/core/core.go +++ b/core/core.go @@ -50,6 +50,9 @@ const ( APICheckQuorumStatusPath string = "/api/check-quorum-status" APIGetPeerDIDTypePath string = "/api/get-peer-didType" APIGetPeerInfoPath string = "/api/get-peer-info" + APIUpdateTokenHashDetails string = "/api/update-tokenhash-details" + APIAddUnpledgeDetails string = "/api/initiate-unpledge" + APISelfTransfer string = "/api/self-transfer" ) const ( @@ -266,12 +269,7 @@ func NewCore(cfg *config.Config, cfgFile string, encKey string, log logger.Logge c.log.Error("Failed to setup quorum manager", "err", err) return nil, err } - err = util.CreateDir(c.cfg.DirPath + "unpledge") - if err != nil { - c.log.Error("Failed to create unpledge", "err", err) - return nil, err - } - c.up, err = unpledge.InitUnPledge(c.s, c.w, c.testNet, c.cfg.DirPath+"unpledge/", c.Unpledge, c.log) + c.up, err = unpledge.InitUnPledge(c.s, c.w, c.testNet, c.log) if err != nil { c.log.Error("Failed to init unpledge", "err", err) return nil, err @@ -329,6 +327,7 @@ func (c *Core) SetupCore() error { c.SetupToken() c.QuroumSetup() c.PinService() + // c.selfTransferService() return nil } diff --git a/core/data_token.go b/core/data_token.go index 3a25f9f1..04d631a4 100644 --- a/core/data_token.go +++ b/core/data_token.go @@ -11,7 +11,6 @@ import ( "github.com/rubixchain/rubixgoplatform/block" "github.com/rubixchain/rubixgoplatform/contract" "github.com/rubixchain/rubixgoplatform/core/model" - "github.com/rubixchain/rubixgoplatform/core/wallet" "github.com/rubixchain/rubixgoplatform/rac" "github.com/rubixchain/rubixgoplatform/token" "github.com/rubixchain/rubixgoplatform/util" @@ -170,7 +169,7 @@ func (c *Core) createDataToken(reqID string, dr *DataTokenReq) *model.BasicRespo br.Message = "Failed to create data token, failed to add rac token to ipfs" return &br } - err = c.w.CreateDataToken(&wallet.DataToken{TokenID: dt, DID: dr.DID, CommitterDID: comDid, BatchID: bid}) + err = c.w.CreateDataToken(&model.DataToken{TokenID: dt, DID: dr.DID, CommitterDID: comDid, BatchID: bid}) if err != nil { c.log.Error("Failed to create data token, write failed", "err", err) br.Message = "Failed to create data token, write failed" @@ -264,7 +263,7 @@ func (c *Core) CommitDataToken(reqID string, did string, batchID string) { dc.OutChan <- br } -func (c *Core) finishDataCommit(br *model.BasicResponse, dts []wallet.DataToken) { +func (c *Core) finishDataCommit(br *model.BasicResponse, dts []model.DataToken) { if br.Status { c.w.CommitDataToken(dts) } else { @@ -305,7 +304,7 @@ func (c *Core) commitDataToken(reqID string, did string, batchID string) *model. } sct := &contract.ContractType{ Type: contract.SCDataTokenCommitType, - PledgeMode: contract.POWPledgeMode, + PledgeMode: contract.PeriodicPledgeMode, TransInfo: tsi, ReqID: reqID, } @@ -378,7 +377,7 @@ func (c *Core) CheckDataToken(dt string) bool { return true } -func (c *Core) GetDataTokens(did string) []wallet.DataToken { +func (c *Core) GetDataTokens(did string) []model.DataToken { dt, err := c.w.GetDataTokenByDID(did) if err != nil { c.log.Error("failed to get data tokens", "err", err) diff --git a/core/model/data_token.go b/core/model/data_token.go index c8164d08..b6841a67 100644 --- a/core/model/data_token.go +++ b/core/model/data_token.go @@ -1,8 +1,14 @@ package model -import "github.com/rubixchain/rubixgoplatform/core/wallet" +type DataToken struct { + TokenID string `gorm:"column:token_id;primaryKey" json:"token_id"` + DID string `gorm:"column:did" json:"did"` + CommitterDID string `gorm:"column:commiter_did" json:"comiter_did"` + BatchID string `gorm:"column:batch_id" json:"batch_id"` + TokenStatus int `gorm:"column:token_status;" json:"token_status"` +} type DataTokenResponse struct { BasicResponse - Tokens []wallet.DataToken `json:"tokens"` + Tokens []DataToken `json:"tokens"` } diff --git a/core/model/quorum.go b/core/model/quorum.go index ac522c68..d275d024 100644 --- a/core/model/quorum.go +++ b/core/model/quorum.go @@ -31,3 +31,24 @@ type QuorumSetup struct { Password string `json:"password"` PrivKeyPassword string `json:"priv_password"` } + +type AddUnpledgeDetailsRequest struct { + TransactionHash string `json:"transaction_hash"` + QuorumDID string `json:"quorum_did"` + PledgeTokenHashes []string `json:"pledge_token_hashes"` + TransactionEpoch int64 `json:"transaction_epoch"` +} + +type InitiateUnpledgeResponse struct { + BasicResponse +} + +type CheckAllTokenOwnershipRequest struct { + TransTokens []string `json:"trans_tokens"` + OwnerDID string `json:"owner_did"` +} + +type CheckAllTokenOwnershipResponse struct { + BasicResponse + AllTokensOwned bool `json:"all_tokens_owned"` +} diff --git a/core/model/tokens.go b/core/model/tokens.go index 8640917a..70022ec2 100644 --- a/core/model/tokens.go +++ b/core/model/tokens.go @@ -42,12 +42,23 @@ type DIDAccountInfo struct { LockedRBT float64 `json:"locked_rbt"` } -type TokenDetial struct { +type TokenDetail struct { Token string `json:"token"` Status int `json:"status"` } type TokenResponse struct { BasicResponse - TokenDetials []TokenDetial `json:"token_detials"` + TokenDetails []TokenDetail `json:"token_detials"` +} + +type PledgedTokenStateDetails struct { + DID string `json:"did"` + TokensPledged string `json:"token"` + TokenStateHash string `json:"token_state"` +} + +type TokenStateResponse struct { + BasicResponse + PledgedTokenStateDetails []PledgedTokenStateDetails `json:"token_state_details"` } diff --git a/core/model/txndetails.go b/core/model/txndetails.go index 18f4158e..6406f649 100644 --- a/core/model/txndetails.go +++ b/core/model/txndetails.go @@ -1,13 +1,37 @@ package model -import "github.com/rubixchain/rubixgoplatform/core/wallet" +import ( + "time" +) + +type TransactionDetails struct { + TransactionID string `gorm:"column:transaction_id;primaryKey"` + TransactionType string `gorm:"column:transaction_type"` + BlockID string `gorm:"column:block_id"` + Mode int `gorm:"column:mode"` + SenderDID string `gorm:"column:sender_did"` + ReceiverDID string `gorm:"column:receiver_did"` + Amount float64 `gorm:"column:amount"` + TotalTime float64 `gorm:"column:total_time"` + Comment string `gorm:"column:comment"` + DateTime time.Time `gorm:"column:date_time"` + Status bool `gorm:"column:status"` + DeployerDID string `gorm:"column:deployer_did"` + Epoch int64 `gorm:"column:epoch"` +} + +type TransactionCount struct { + DID string + TxnSend int + TxnReceived int +} type TxnDetails struct { BasicResponse - TxnDetails []wallet.TransactionDetails + TxnDetails []TransactionDetails } type TxnCountForDID struct { BasicResponse - TxnCount []wallet.TransactionCount + TxnCount []TransactionCount } diff --git a/core/nft.go b/core/nft.go index 63de2ea2..94bfd2a7 100644 --- a/core/nft.go +++ b/core/nft.go @@ -299,7 +299,7 @@ func (c *Core) addNFTSaleContract(reqID string, sr *NFTSaleReq) *model.BasicResp } sct := &contract.ContractType{ Type: contract.SCNFTSaleContractType, - PledgeMode: contract.POWPledgeMode, + PledgeMode: contract.PeriodicPledgeMode, TotalRBTs: totalAmount, TransInfo: &contract.TransInfo{ SenderDID: did, diff --git a/core/quorum_initiator.go b/core/quorum_initiator.go index 0f62edff..37b804e7 100644 --- a/core/quorum_initiator.go +++ b/core/quorum_initiator.go @@ -1,6 +1,7 @@ package core import ( + "bytes" "errors" "fmt" "strconv" @@ -8,6 +9,7 @@ import ( "sync" "time" + ipfsnode "github.com/ipfs/go-ipfs-api" "github.com/rubixchain/rubixgoplatform/block" "github.com/rubixchain/rubixgoplatform/contract" "github.com/rubixchain/rubixgoplatform/core/ipfsport" @@ -28,6 +30,7 @@ const ( NFTSaleContractMode SmartContractDeployMode SmartContractExecuteMode + SelfTransferMode ) const ( AlphaQuorumType int = iota @@ -47,6 +50,7 @@ type ConensusRequest struct { SmartContractToken string `json:"smart_contract_token"` ExecuterPeerID string `json:"executor_peer_id"` TransactionID string `json:"transaction_id"` + TransactionEpoch int `json:"transaction_epoch"` } type ConensusReply struct { @@ -95,17 +99,21 @@ type SignatureReply struct { } type UpdatePledgeRequest struct { - Mode int `json:"mode"` - PledgedTokens []string `json:"pledged_tokens"` - TokenChainBlock []byte `json:"token_chain_block"` + Mode int `json:"mode"` + PledgedTokens []string `json:"pledged_tokens"` + TokenChainBlock []byte `json:"token_chain_block"` + TransferredTokenStateHashes []string `json:"token_state_hash_info"` + TransactionID string `json:"transaction_id"` + TransactionEpoch int `json:"transaction_epoch"` } type SendTokenRequest struct { - Address string `json:"peer_id"` - TokenInfo []contract.TokenInfo `json:"token_info"` - TokenChainBlock []byte `json:"token_chain_block"` - QuorumList []string `json:"quorum_list"` - QuorumInfo []QuorumDIDPeerMap `json:"quorum_info"` + Address string `json:"peer_id"` + TokenInfo []contract.TokenInfo `json:"token_info"` + TokenChainBlock []byte `json:"token_chain_block"` + QuorumList []string `json:"quorum_list"` + QuorumInfo []QuorumDIDPeerMap `json:"quorum_info"` + TransactionEpoch int `json:"transaction_epoch"` } type PledgeReply struct { @@ -156,8 +164,10 @@ func (c *Core) QuroumSetup() { c.l.AddRoute(APIReqPledgeToken, "POST", c.reqPledgeToken) c.l.AddRoute(APIUpdatePledgeToken, "POST", c.updatePledgeToken) c.l.AddRoute(APISignatureRequest, "POST", c.signatureRequest) - c.l.AddRoute(APISendReceiverToken, "POST", c.updateReceiverToken) + c.l.AddRoute(APISendReceiverToken, "POST", c.updateReceiverTokenHandle) c.l.AddRoute(APIUnlockTokens, "POST", c.unlockTokens) + c.l.AddRoute(APIUpdateTokenHashDetails, "POST", c.updateTokenHashDetails) + c.l.AddRoute(APIAddUnpledgeDetails, "POST", c.addUnpledgeDetails) if c.arbitaryMode { c.l.AddRoute(APIMapDIDArbitration, "POST", c.mapDIDArbitration) c.l.AddRoute(APICheckDIDArbitration, "GET", c.chekDIDArbitration) @@ -232,7 +242,6 @@ func (c *Core) SetupQuorum(didStr string, pwd string, pvtKeyPwd string) error { } } - c.up.RunUnpledge() return nil } @@ -280,7 +289,7 @@ func (c *Core) sendQuorumCredit(cr *ConensusRequest) { // c.qlock.Unlock() } -func (c *Core) initiateConsensus(cr *ConensusRequest, sc *contract.Contract, dc did.DIDCrypto) (*wallet.TransactionDetails, map[string]map[string]float64, error) { +func (c *Core) initiateConsensus(cr *ConensusRequest, sc *contract.Contract, dc did.DIDCrypto) (*model.TransactionDetails, map[string]map[string]float64, error) { cs := ConsensusStatus{ Credit: CreditScore{ Credit: make([]CreditSignature, 0), @@ -294,9 +303,10 @@ func (c *Core) initiateConsensus(cr *ConensusRequest, sc *contract.Contract, dc }, } reqPledgeTokens := float64(0) + // TODO:: Need to correct for part tokens switch cr.Mode { - case RBTTransferMode, NFTSaleContractMode: + case RBTTransferMode, NFTSaleContractMode, SelfTransferMode: ti := sc.GetTransTokenInfo() for i := range ti { reqPledgeTokens = reqPledgeTokens + ti[i].TokenValue @@ -403,7 +413,7 @@ func (c *Core) initiateConsensus(cr *ConensusRequest, sc *contract.Contract, dc c.log.Error("Failed to pledge token", "err", err) return nil, nil, err } - c.sendQuorumCredit(cr) + ti := sc.GetTransTokenInfo() c.qlock.Lock() pds := c.pd[cr.ReqID] @@ -422,7 +432,9 @@ func (c *Core) initiateConsensus(cr *ConensusRequest, sc *contract.Contract, dc } } } - if cr.Mode == RBTTransferMode { + + switch cr.Mode { + case RBTTransferMode: rp, err := c.getPeer(cr.ReceiverPeerID+"."+sc.GetReceiverDID(), "") if err != nil { c.log.Error("Receiver not connected", "err", err) @@ -430,10 +442,11 @@ func (c *Core) initiateConsensus(cr *ConensusRequest, sc *contract.Contract, dc } defer rp.Close() sr := SendTokenRequest{ - Address: cr.SenderPeerID + "." + sc.GetSenderDID(), - TokenInfo: ti, - TokenChainBlock: nb.GetBlock(), - QuorumList: cr.QuorumList, + Address: cr.SenderPeerID + "." + sc.GetSenderDID(), + TokenInfo: ti, + TokenChainBlock: nb.GetBlock(), + QuorumList: cr.QuorumList, + TransactionEpoch: cr.TransactionEpoch, } //fetching quorums' info from PeerDIDTable to share with the receiver @@ -517,13 +530,57 @@ func (c *Core) initiateConsensus(cr *ConensusRequest, sc *contract.Contract, dc return nil, nil, fmt.Errorf("unable to send tokens to receiver, " + br.Message) } - //trigger pledge finality to the quorum - pledgeFinalityError := c.quorumPledgeFinality(cr, nb) + // br.Result will contain the new token state after sending tokens to receiver as a response to APISendReceiverToken + newtokenhashresult, ok := br.Result.([]interface{}) + if !ok { + c.log.Error("Type assertion to string failed") + return nil, nil, fmt.Errorf("Type assertion to string failed") + } + var newtokenhashes []string + for i, newTokenHash := range newtokenhashresult { + statehash, ok := newTokenHash.(string) + if !ok { + c.log.Error("Type assertion to string failed at index", i) + return nil, nil, fmt.Errorf("Type assertion to string failed at index", i) + } + newtokenhashes = append(newtokenhashes, statehash) + } + + //trigger pledge finality to the quorum and also adding the new tokenstate hash details for transferred tokens to quorum + pledgeFinalityError := c.quorumPledgeFinality(cr, nb, newtokenhashes, tid) if pledgeFinalityError != nil { c.log.Error("Pledge finlaity not achieved", "err", err) return nil, nil, pledgeFinalityError } + //Checking prev block details (i.e. the latest block before transferring) by sender. Sender will connect with old quorums, and update about the exhausted token state hashes to quorums for them to unpledge their tokens. + for _, tokeninfo := range ti { + b := c.w.GetLatestTokenBlock(tokeninfo.Token, tokeninfo.TokenType) + signers, _ := b.GetSigner() + + //if signer is similar to sender did skip this token, as the block is the genesys block + if signers[0] == sc.GetSenderDID() { + continue + } + //concat tokenId and BlockID + bid, _ := b.GetBlockID(tokeninfo.Token) + prevtokenIDTokenStateData := tokeninfo.Token + bid + prevtokenIDTokenStateBuffer := bytes.NewBuffer([]byte(prevtokenIDTokenStateData)) + + //add to ipfs get only the hash of the token+tokenstate. This is the hash just before transferring i.e. the exhausted token state hash, and updating in Sender side + prevtokenIDTokenStateHash, _ := c.ipfs.Add(prevtokenIDTokenStateBuffer, ipfsnode.Pin(false), ipfsnode.OnlyHash(true)) + + //send this exhausted hash to old quorums to unpledge + for _, signer := range signers { + signer_peeerId := c.w.GetPeerID(signer) + signer_addr := signer_peeerId + "." + signer + p, _ := c.getPeer(signer_addr, "") + m := make(map[string]string) + m["tokenIDTokenStateHash"] = prevtokenIDTokenStateHash + _ = p.SendJSONRequest("POST", APIUpdateTokenHashDetails, m, nil, nil, true) + } + } + err = c.w.TokensTransferred(sc.GetSenderDID(), ti, nb, rp.IsLocal()) if err != nil { c.log.Error("Failed to transfer tokens", "err", err) @@ -540,7 +597,7 @@ func (c *Core) initiateConsensus(cr *ConensusRequest, sc *contract.Contract, dc return nil, nil, err } - td := wallet.TransactionDetails{ + td := model.TransactionDetails{ TransactionID: tid, TransactionType: nb.GetTransType(), BlockID: nbid, @@ -550,15 +607,136 @@ func (c *Core) initiateConsensus(cr *ConensusRequest, sc *contract.Contract, dc Comment: sc.GetComment(), DateTime: time.Now(), Status: true, + Epoch: int64(cr.TransactionEpoch), + } + + err = c.initiateUnpledgingProcess(cr, td.TransactionID, td.Epoch) + if err != nil { + c.log.Error("Failed to store transactiond details with quorum ", "err", err) + return nil, nil, err } + return &td, pl, nil - } else if cr.Mode == DTCommitMode { + case SelfTransferMode: + var quorumInfo []QuorumDIDPeerMap = make([]QuorumDIDPeerMap, 0) + var selfAddress string = cr.ReceiverPeerID + "." + sc.GetReceiverDID() + + //fetching quorums' info from PeerDIDTable to share with the receiver + for _, qrm := range cr.QuorumList { + //fetch peer id & did of the quorum + qpid, qdid, ok := util.ParseAddress(qrm) + if !ok { + c.log.Error("could not parse quorum address:", qrm) + } + if qpid == "" { + qpid = c.w.GetPeerID(qdid) + } + + var qrmInfo QuorumDIDPeerMap + //fetch did type of the quorum + qDidType, err := c.w.GetPeerDIDType(qdid) + if err != nil { + c.log.Error("could not fetch did type for quorum:", qdid, "error", err) + } + if qDidType == -1 { + c.log.Info("did type is empty for quorum:", qdid, "connecting & fetching from quorum") + didtype_, msg, err := c.GetPeerdidType_fromPeer(qpid, qdid, dc.GetDID()) + if err != nil { + c.log.Error("error", err, "msg", msg) + qrmInfo.DIDType = nil + } else { + qDidType = didtype_ + qrmInfo.DIDType = &qDidType + } + } else { + qrmInfo.DIDType = &qDidType + } + //add quorum details to the data to be shared + qrmInfo.DID = qdid + qrmInfo.PeerID = qpid + quorumInfo = append(quorumInfo, qrmInfo) + } + + // Self update for self transfer tokens + updatedTokenHashes, err := c.updateReceiverToken(selfAddress, "", ti, nb.GetBlock(), cr.QuorumList, quorumInfo, cr.TransactionEpoch) + if err != nil { + errMsg := fmt.Errorf("failed while update of self transfer tokens, err: %v", err) + c.log.Error(errMsg.Error()) + return nil, nil, errMsg + + } + + //trigger pledge finality to the quorum and also adding the new tokenstate hash details for transferred tokens to quorum + pledgeFinalityError := c.quorumPledgeFinality(cr, nb, updatedTokenHashes, tid) + if pledgeFinalityError != nil { + c.log.Error("Pledge finlaity not achieved", "err", err) + return nil, nil, pledgeFinalityError + } + + //Checking prev block details (i.e. the latest block before transferring) by sender. Sender will connect with old quorums, and update about the exhausted token state hashes to quorums for them to unpledge their tokens. + for _, tokeninfo := range ti { + b := c.w.GetLatestTokenBlock(tokeninfo.Token, tokeninfo.TokenType) + signers, _ := b.GetSigner() + + //if signer is similar to sender did skip this token, as the block is the genesys block + if signers[0] == sc.GetSenderDID() { + continue + } + // Contrary to general RBT transfer where we can take the latest block ID since the token chain wasn't updated, + // in case of Self Transfer, the tokechain gets updated after calling updateReceiverToken, hence we have to consider + // the previous block ID + bid, _ := b.GetPrevBlockID(tokeninfo.Token) + + prevtokenIDTokenStateData := tokeninfo.Token + bid + prevtokenIDTokenStateBuffer := bytes.NewBuffer([]byte(prevtokenIDTokenStateData)) + + //add to ipfs get only the hash of the token+tokenstate. This is the hash just before transferring i.e. the exhausted token state hash, and updating in Sender side + prevtokenIDTokenStateHash, _ := c.ipfs.Add(prevtokenIDTokenStateBuffer, ipfsnode.Pin(false), ipfsnode.OnlyHash(true)) + + //send this exhausted hash to old quorums to unpledge + for _, signer := range signers { + signer_peeerId := c.w.GetPeerID(signer) + signer_addr := signer_peeerId + "." + signer + p, _ := c.getPeer(signer_addr, "") + m := make(map[string]string) + m["tokenIDTokenStateHash"] = prevtokenIDTokenStateHash + _ = p.SendJSONRequest("POST", APIUpdateTokenHashDetails, m, nil, nil, true) + } + } + + nbid, err := nb.GetBlockID(ti[0].Token) + if err != nil { + c.log.Error("Failed to get block id", "err", err) + return nil, nil, err + } + + td := model.TransactionDetails{ + TransactionID: tid, + TransactionType: nb.GetTransType(), + BlockID: nbid, + Mode: wallet.SendMode, + SenderDID: sc.GetSenderDID(), + ReceiverDID: sc.GetReceiverDID(), + Comment: sc.GetComment(), + DateTime: time.Now(), + Status: true, + Epoch: int64(cr.TransactionEpoch), + } + + err = c.initiateUnpledgingProcess(cr, td.TransactionID, td.Epoch) + if err != nil { + c.log.Error("Failed to store transactiond details with quorum ", "err", err) + return nil, nil, err + } + + return &td, pl, nil + case DTCommitMode: err = c.w.CreateTokenBlock(nb) if err != nil { c.log.Error("Failed to create token block", "err", err) return nil, nil, err } - td := wallet.TransactionDetails{ + td := model.TransactionDetails{ TransactionID: tid, TransactionType: nb.GetTransType(), DateTime: time.Now(), @@ -566,13 +744,13 @@ func (c *Core) initiateConsensus(cr *ConensusRequest, sc *contract.Contract, dc } //trigger pledge finality to the quorum - pledgeFinalityError := c.quorumPledgeFinality(cr, nb) + pledgeFinalityError := c.quorumPledgeFinality(cr, nb, nil, tid) if pledgeFinalityError != nil { c.log.Error("Pledge finlaity not achieved", "err", err) return nil, nil, pledgeFinalityError } return &td, pl, nil - } else if cr.Mode == SmartContractDeployMode { + case SmartContractDeployMode: //Create tokechain for the smart contract token and add genesys block err = c.w.AddTokenBlock(cr.SmartContractToken, nb) if err != nil { @@ -611,8 +789,14 @@ func (c *Core) initiateConsensus(cr *ConensusRequest, sc *contract.Contract, dc return nil, nil, err } - //trigger pledge finality to the quorum - pledgeFinalityError := c.quorumPledgeFinality(cr, nb) + //Latest Smart contract token hash after being deployed. + scTokenStateData := cr.SmartContractToken + newBlockId + tokenIDTokenStateBuffer := bytes.NewBuffer([]byte(scTokenStateData)) + newtokenIDTokenStateHash, err := c.ipfs.Add(tokenIDTokenStateBuffer, ipfsnode.Pin(false), ipfsnode.OnlyHash(true)) + c.log.Info(fmt.Sprintf("New smart contract token hash after being deployed : %s", newtokenIDTokenStateHash)) + + //trigger pledge finality to the quorum and adding the details in token hash table + pledgeFinalityError := c.quorumPledgeFinality(cr, nb, []string{newtokenIDTokenStateHash}, tid) if pledgeFinalityError != nil { c.log.Error("Pledge finlaity not achieved", "err", err) return nil, nil, pledgeFinalityError @@ -631,7 +815,7 @@ func (c *Core) initiateConsensus(cr *ConensusRequest, sc *contract.Contract, dc c.log.Error("Failed to publish smart contract deployed info") } - txnDetails := wallet.TransactionDetails{ + txnDetails := model.TransactionDetails{ TransactionID: tid, TransactionType: nb.GetTransType(), BlockID: newBlockId, @@ -640,9 +824,20 @@ func (c *Core) initiateConsensus(cr *ConensusRequest, sc *contract.Contract, dc Comment: sc.GetComment(), DateTime: time.Now(), Status: true, + Epoch: int64(cr.TransactionEpoch), + } + + err = c.initiateUnpledgingProcess(cr, txnDetails.TransactionID, txnDetails.Epoch) + if err != nil { + c.log.Error("Failed to store transactiond details with quorum ", "err", err) + return nil, nil, err } + return &txnDetails, pl, nil - } else { //execute mode + case SmartContractExecuteMode: + //Get the latest block details before being executed to get the old signers + b := c.w.GetLatestTokenBlock(cr.SmartContractToken, nb.GetTokenType(cr.SmartContractToken)) + signers, _ := b.GetSigner() //Create tokechain for the smart contract token and add genesys block err = c.w.AddTokenBlock(cr.SmartContractToken, nb) @@ -663,8 +858,14 @@ func (c *Core) initiateConsensus(cr *ConensusRequest, sc *contract.Contract, dc return nil, nil, err } - //trigger pledge finality to the quorum - pledgeFinalityError := c.quorumPledgeFinality(cr, nb) + //Latest Smart contract token hash after being executed. + scTokenStateData := cr.SmartContractToken + newBlockId + tokenIDTokenStateBuffer := bytes.NewBuffer([]byte(scTokenStateData)) + newtokenIDTokenStateHash, err := c.ipfs.Add(tokenIDTokenStateBuffer, ipfsnode.Pin(false), ipfsnode.OnlyHash(true)) + c.log.Info(fmt.Sprintf("New smart contract token hash after being executed : %s", newtokenIDTokenStateHash)) + + //trigger pledge finality to the quorum and adding the details in token hash table + pledgeFinalityError := c.quorumPledgeFinality(cr, nb, []string{newtokenIDTokenStateHash}, tid) if pledgeFinalityError != nil { c.log.Error("Pledge finlaity not achieved", "err", err) return nil, nil, pledgeFinalityError @@ -683,7 +884,21 @@ func (c *Core) initiateConsensus(cr *ConensusRequest, sc *contract.Contract, dc c.log.Error("Failed to publish smart contract Executed info") } - txnDetails := wallet.TransactionDetails{ + //inform old quorums about exhausted smart contract token hash + prevBlockId, _ := nb.GetPrevBlockID((cr.SmartContractToken)) + scTokenStateDataOld := cr.SmartContractToken + prevBlockId + scTokenStateDataOldBuffer := bytes.NewBuffer([]byte(scTokenStateDataOld)) + oldsctokenIDTokenStateHash, _ := c.ipfs.Add(scTokenStateDataOldBuffer, ipfsnode.Pin(false), ipfsnode.OnlyHash(true)) + for _, signer := range signers { + signer_peeerId := c.w.GetPeerID(signer) + signer_addr := signer_peeerId + "." + signer + p, _ := c.getPeer(signer_addr, "") + m := make(map[string]string) + m["tokenIDTokenStateHash"] = oldsctokenIDTokenStateHash + _ = p.SendJSONRequest("POST", APIUpdateTokenHashDetails, m, nil, nil, true) + } + + txnDetails := model.TransactionDetails{ TransactionID: tid, TransactionType: nb.GetTransType(), BlockID: newBlockId, @@ -692,12 +907,89 @@ func (c *Core) initiateConsensus(cr *ConensusRequest, sc *contract.Contract, dc Comment: sc.GetComment(), DateTime: time.Now(), Status: true, + Epoch: int64(cr.TransactionEpoch), + } + + err = c.initiateUnpledgingProcess(cr, txnDetails.TransactionID, txnDetails.Epoch) + if err != nil { + c.log.Error("Failed to store transactiond details with quorum ", "err", err) + return nil, nil, err } + return &txnDetails, pl, nil + default: + err := fmt.Errorf("invalid consensus request mode: %v", cr.Mode) + c.log.Error(err.Error()) + return nil, nil, err } } -func (c *Core) quorumPledgeFinality(cr *ConensusRequest, newBlock *block.Block) error { +func (c *Core) initiateUnpledgingProcess(cr *ConensusRequest, transactionHash string, transactionEpoch int64) error { + // Get the information about Pledging Quorum from pledged tokens + // TODO: Need to refactor after incorporating Distributed Pledging + c.qlock.Lock() + pd, ok1 := c.pd[cr.ReqID] + cs, ok2 := c.quorumRequest[cr.ReqID] + c.qlock.Unlock() + + if !ok1 || !ok2 { + c.log.Error("invalid consensus request for quorum transaction detail storage") + return errors.New("invalid consensus request for quorum transaction detail storage") + } + + if len(pd.PledgedTokens) == 0 { + c.log.Error("unable to get pledged tokens") + return errors.New("unable to get pledged tokens") + } + + for did, pledgeTokenHashes := range pd.PledgedTokens { + p, ok := cs.P[did] + if !ok { + c.log.Error("unable to get the peer detail") + return fmt.Errorf("unable to get the peer detail") + } + if p == nil { + c.log.Error("peer object is returned as nil") + return fmt.Errorf("peer object is returned as nil") + } + var qAddress string + for _, quorumValue := range cr.QuorumList { + // Check if the value of p.GetPeerDID() exists in the QuorumList as a substring + if strings.Contains(quorumValue, p.GetPeerDID()) { + qAddress = quorumValue + } + } + + qPeer, err := c.getPeer(qAddress, "") + if err != nil { + c.log.Error("Quorum not connected (storing tx info)", "err", err) + return err + } + defer qPeer.Close() + + var br model.BasicResponse + initiateUnpledgeRequest := &model.AddUnpledgeDetailsRequest{ + TransactionHash: transactionHash, + QuorumDID: qPeer.GetPeerDID(), + PledgeTokenHashes: pledgeTokenHashes, + TransactionEpoch: transactionEpoch, + } + + err = qPeer.SendJSONRequest("POST", APIAddUnpledgeDetails, nil, initiateUnpledgeRequest, &br, true) + if err != nil { + c.log.Error(err.Error()) + return err + } + if !br.Status { + c.log.Error(br.Message) + return fmt.Errorf(br.Message) + } + } + + return nil +} + +func (c *Core) quorumPledgeFinality(cr *ConensusRequest, newBlock *block.Block, newTokenStateHashes []string, transactionId string) error { c.log.Debug("Proceeding for pledge finality") c.qlock.Lock() pd, ok1 := c.pd[cr.ReqID] @@ -732,9 +1024,17 @@ func (c *Core) quorumPledgeFinality(cr *ConensusRequest, newBlock *block.Block) defer qPeer.Close() var br model.BasicResponse ur := UpdatePledgeRequest{ - Mode: cr.Mode, - PledgedTokens: v, - TokenChainBlock: newBlock.GetBlock(), + Mode: cr.Mode, + PledgedTokens: v, + TokenChainBlock: newBlock.GetBlock(), + TransactionID: transactionId, + TransferredTokenStateHashes: nil, + TransactionEpoch: cr.TransactionEpoch, + } + + if newTokenStateHashes != nil { + // ur.TransferredTokenStateHashes = newTokenStateHashes[countofTokenStateHash : countofTokenStateHash+len(v)] + ur.TransferredTokenStateHashes = newTokenStateHashes } err = qPeer.SendJSONRequest("POST", APIUpdatePledgeToken, nil, &ur, &br, true) @@ -1092,6 +1392,7 @@ func (c *Core) pledgeQuorumToken(cr *ConensusRequest, sc *contract.Contract, tid SmartContract: sc.GetBlock(), GenesisBlock: smartContractGensisBlock, PledgeDetails: ptds, + Epoch: cr.TransactionEpoch, } } else if cr.Mode == SmartContractExecuteMode { bti.ExecutorDID = sc.GetExecutorDID() @@ -1103,6 +1404,7 @@ func (c *Core) pledgeQuorumToken(cr *ConensusRequest, sc *contract.Contract, tid SmartContract: sc.GetBlock(), PledgeDetails: ptds, SmartContractData: sc.GetSmartContractData(), + Epoch: cr.TransactionEpoch, } } else { //Fetching sender signature to add it to transaction details @@ -1131,6 +1433,7 @@ func (c *Core) pledgeQuorumToken(cr *ConensusRequest, sc *contract.Contract, tid SmartContract: sc.GetBlock(), PledgeDetails: ptds, SenderSignature: sender_sign, + Epoch: cr.TransactionEpoch, } } diff --git a/core/quorum_recv.go b/core/quorum_recv.go index 867e3f97..fc59f6d8 100644 --- a/core/quorum_recv.go +++ b/core/quorum_recv.go @@ -5,7 +5,6 @@ import ( "encoding/base64" "encoding/json" "fmt" - "io/ioutil" "net/http" "strconv" "strings" @@ -15,6 +14,7 @@ import ( ipfsnode "github.com/ipfs/go-ipfs-api" "github.com/rubixchain/rubixgoplatform/block" "github.com/rubixchain/rubixgoplatform/contract" + "github.com/rubixchain/rubixgoplatform/core/ipfsport" "github.com/rubixchain/rubixgoplatform/core/model" "github.com/rubixchain/rubixgoplatform/core/service" "github.com/rubixchain/rubixgoplatform/core/wallet" @@ -24,6 +24,37 @@ import ( "github.com/rubixchain/rubixgoplatform/wrapper/ensweb" ) +func (c *Core) addUnpledgeDetails(req *ensweb.Request) *ensweb.Result { + resp := model.BasicResponse{ + Status: false, + } + + var serverReq *model.AddUnpledgeDetailsRequest + c.l.ParseJSON(req, &serverReq) + + var transactionID string = serverReq.TransactionHash + var quorumDID string = serverReq.QuorumDID + var pledgeTokenHashes []string = serverReq.PledgeTokenHashes + var transactionEpoch int64 = serverReq.TransactionEpoch + + if len(pledgeTokenHashes) == 0 { + c.log.Error("unable to get information about pledge token hashes") + return c.l.RenderJSON(req, &resp, http.StatusOK) + } + + // Add Unpledge details to UnpledgeQueue + pledgeTokenHashesStrArr := strings.Join(pledgeTokenHashes, ",") + err := c.up.AddUnPledge(transactionID, pledgeTokenHashesStrArr, transactionEpoch, quorumDID) + if err != nil { + resp.Message = fmt.Sprintf("Error while adding record to UnpledgeQueue table for txId: %v, error: %v", transactionID, err.Error()) + c.log.Error(fmt.Sprintf("Error while adding record to UnpledgeQueue table for txId: %v, error: %v", transactionID, err.Error())) + return c.l.RenderJSON(req, &resp, http.StatusOK) + } + + resp.Status = true + return c.l.RenderJSON(req, &resp, http.StatusOK) +} + func (c *Core) creditStatus(req *ensweb.Request) *ensweb.Result { // ::TODO:: Get proper credit score did := c.l.GetQuerry(req, "did") @@ -205,64 +236,6 @@ func (c *Core) quorumRBTConsensus(req *ensweb.Request, did string, qdc didcrypto c.log.Debug("Finished Tokenstate check") - //check if token is pledgedtoken - wt := sc.GetTransTokenInfo() - - for i := range wt { - b := c.w.GetLatestTokenBlock(wt[i].Token, wt[i].TokenType) - if b == nil { - c.log.Error("pledge token check Failed, failed to get latest block") - crep.Message = "pledge token check Failed, failed to get latest block" - return c.l.RenderJSON(req, &crep, http.StatusOK) - } - if c.checkIsPledged(b) { - c.log.Error("Pledge Token check Failed, Token ", wt[i], " is Pledged Token") - crep.Message = "Pledge Token check Failed, Token " + wt[i].Token + " is Pledged Token" - return c.l.RenderJSON(req, &crep, http.StatusOK) - } - if c.checkIsUnpledged(b) { - unpledgeId := c.getUnpledgeId(wt[i].Token, wt[i].TokenType) - if unpledgeId == "" { - c.log.Error("Failed to fetch proof file CID") - crep.Message = "Failed to fetch proof file CID" - return c.l.RenderJSON(req, &crep, http.StatusOK) - } - err := c.ipfs.Get(unpledgeId, c.cfg.DirPath+"unpledge") - if err != nil { - c.log.Error("Failed to fetch proof file") - crep.Message = "Failed to fetch proof file, err " + err.Error() - return c.l.RenderJSON(req, &crep, http.StatusOK) - } - pcb, err := ioutil.ReadFile(c.cfg.DirPath + "unpledge/" + unpledgeId) - if err != nil { - c.log.Error("Invalid file", "err", err) - crep.Message = "Invalid file,err " + err.Error() - return c.l.RenderJSON(req, &crep, http.StatusOK) - } - pcs := util.BytesToString(pcb) - - senderAddr := cr.SenderPeerID + "." + sc.GetSenderDID() - rdid, tid, err := c.getProofverificationDetails(wt[i].Token, senderAddr, wt[i].TokenType) - if err != nil { - c.log.Error("Failed to get pledged for token reciveer did", "err", err) - crep.Message = "Failed to get pledged for token reciveer did" - return c.l.RenderJSON(req, &crep, http.StatusOK) - } - pv, err := c.up.ProofVerification(wt[i].Token, pcs, rdid, tid, wt[i].TokenType) - if err != nil { - c.log.Error("Proof Verification Failed due to error ", err) - crep.Message = "Proof Verification Failed due to error " + err.Error() - return c.l.RenderJSON(req, &crep, http.StatusOK) - } - if !pv { - c.log.Debug("Proof of Work for Unpledge not verified") - crep.Message = "Proof of Work for Unpledge not verified" - return c.l.RenderJSON(req, &crep, http.StatusOK) - } - c.log.Debug("Proof of work verified") - } - } - qHash := util.CalculateHash(sc.GetBlock(), "SHA3-256") qsb, ppb, err := qdc.Sign(util.HexToStr(qHash)) if err != nil { @@ -535,7 +508,7 @@ func (c *Core) quorumConensus(req *ensweb.Request) *ensweb.Result { return c.l.RenderJSON(req, &crep, http.StatusOK) } switch cr.Mode { - case RBTTransferMode: + case RBTTransferMode, SelfTransferMode: c.log.Debug("RBT consensus started") return c.quorumRBTConsensus(req, did, qdc, &cr) case DTCommitMode: @@ -632,173 +605,215 @@ func (c *Core) reqPledgeToken(req *ensweb.Request) *ensweb.Result { return c.l.RenderJSON(req, &presp, http.StatusOK) } -func (c *Core) updateReceiverToken(req *ensweb.Request) *ensweb.Result { - did := c.l.GetQuerry(req, "did") - var sr SendTokenRequest +func (c *Core) updateReceiverToken( + senderAddress string, receiverAddress string, tokenInfo []contract.TokenInfo, tokenChainBlock []byte, + quorumList []string, quorumInfo []QuorumDIDPeerMap, transactionEpoch int, +) ([]string, error) { + var receiverPeerId string = "" + var receiverDID string = "" - err := c.l.ParseJSON(req, &sr) - crep := model.BasicResponse{ - Status: false, + if receiverAddress != "" { + var ok bool + receiverPeerId, receiverDID, ok = util.ParseAddress(receiverAddress) + if !ok { + return nil, fmt.Errorf("Unable to parse receiver address: %v", receiverAddress) + } + } else { + var ok bool + receiverPeerId, receiverDID, ok = util.ParseAddress(senderAddress) + if !ok { + return nil, fmt.Errorf("Unable to parse receiver address: %v", senderAddress) + } } - if err != nil { - c.log.Error("Failed to parse json request", "err", err) - crep.Message = "Failed to parse json request" - return c.l.RenderJSON(req, &crep, http.StatusOK) - } - b := block.InitBlock(sr.TokenChainBlock, nil) + b := block.InitBlock(tokenChainBlock, nil) if b == nil { - c.log.Error("Invalid token chain block", "err", err) - crep.Message = "Invalid token chain block" - return c.l.RenderJSON(req, &crep, http.StatusOK) + return nil, fmt.Errorf("invalid token chain block") } - p, err := c.getPeer(sr.Address, "") - if err != nil { - c.log.Error("failed to get peer", "err", err) - crep.Message = "failed to get peer" - return c.l.RenderJSON(req, &crep, http.StatusOK) - } - defer p.Close() - for _, ti := range sr.TokenInfo { - t := ti.Token - pblkID, err := b.GetPrevBlockID(t) - if err != nil { - c.log.Error("failed to sync token chain block, missing previous block id for token ", t, " err : ", err) - crep.Message = "failed to sync token chain block, missing previous block id for token " + t - return c.l.RenderJSON(req, &crep, http.StatusOK) - } - err = c.syncTokenChainFrom(p, pblkID, t, ti.TokenType) + var senderPeer *ipfsport.Peer + + if receiverAddress != "" { + var err error + senderPeer, err = c.getPeer(senderAddress, "") if err != nil { - errMsg := fmt.Sprintf("failed to sync tokenchain Token: %v, issueType: %v", t, TokenChainNotSynced) - c.log.Error(errMsg, "err", err) - crep.Message = errMsg - return c.l.RenderJSON(req, &crep, http.StatusOK) + return nil, fmt.Errorf("failed to get peer : %v", err.Error()) } + defer senderPeer.Close() - if c.TokenType(PartString) == ti.TokenType { - gb := c.w.GetGenesisTokenBlock(t, ti.TokenType) - if gb == nil { - c.log.Error("failed to get genesis block for token ", t, "err : ", err) - crep.Message = "failed to get genesis block for token " + t - return c.l.RenderJSON(req, &crep, http.StatusOK) + for _, ti := range tokenInfo { + t := ti.Token + pblkID, err := b.GetPrevBlockID(t) + if err != nil { + return nil, fmt.Errorf("failed to sync token chain block, missing previous block id for token %v, error: %v", t, err) } - pt, _, err := gb.GetParentDetials(t) + + err = c.syncTokenChainFrom(senderPeer, pblkID, t, ti.TokenType) if err != nil { - c.log.Error("failed to get parent details for token ", t, " err : ", err) - crep.Message = "failed to get parent details for token " + t - return c.l.RenderJSON(req, &crep, http.StatusOK) + return nil, fmt.Errorf("failed to sync tokenchain Token: %v, issueType: %v", t, TokenChainNotSynced) } - err = c.syncParentToken(p, pt) + + if c.TokenType(PartString) == ti.TokenType { + gb := c.w.GetGenesisTokenBlock(t, ti.TokenType) + if gb == nil { + return nil, fmt.Errorf("failed to get genesis block for token %v, err: %v", t, err) + } + pt, _, err := gb.GetParentDetials(t) + if err != nil { + return nil, fmt.Errorf("failed to get parent details for token %v, err: %v", t, err) + } + err = c.syncParentToken(senderPeer, pt) + if err != nil { + return nil, fmt.Errorf("failed to sync parent token %v childtoken %v err : ", pt, t, err) + } + } + ptcbArray, err := c.w.GetTokenBlock(t, ti.TokenType, pblkID) if err != nil { - c.log.Error("failed to sync parent token ", pt, " childtoken ", t, " err : ", err) - crep.Message = "failed to sync parent token " + pt + " childtoken " + t - return c.l.RenderJSON(req, &crep, http.StatusOK) + return nil, fmt.Errorf("failed to fetch previous block for token: % err : %v", t, err) + } + ptcb := block.InitBlock(ptcbArray, nil) + if c.checkIsPledged(ptcb) { + return nil, fmt.Errorf("Token " + t + " is a pledged Token") } - } - ptcbArray, err := c.w.GetTokenBlock(t, ti.TokenType, pblkID) - if err != nil { - c.log.Error("Failed to fetch previous block for token ", t, " err : ", err) - crep.Message = "Failed to fetch previous block for token " + t - return c.l.RenderJSON(req, &crep, http.StatusOK) - } - ptcb := block.InitBlock(ptcbArray, nil) - if c.checkIsPledged(ptcb) { - c.log.Error("Token is a pledged Token", "token", t) - crep.Message = "Token " + t + " is a pledged Token" - return c.l.RenderJSON(req, &crep, http.StatusOK) } } - results := make([]MultiPinCheckRes, len(sr.TokenInfo)) + senderPeerId, _, ok := util.ParseAddress(senderAddress) + if !ok { + return nil, fmt.Errorf("Unable to parse sender address: %v", senderAddress) + } + + results := make([]MultiPinCheckRes, len(tokenInfo)) var wg sync.WaitGroup - for i, ti := range sr.TokenInfo { + for i, ti := range tokenInfo { t := ti.Token - senderPeerId, _, ok := util.ParseAddress(sr.Address) - if !ok { - c.log.Error("Error occured", "error", err) - crep.Message = "Unable to parse sender address" - return c.l.RenderJSON(req, &crep, http.StatusOK) - } wg.Add(1) - go c.pinCheck(t, i, senderPeerId, c.peerID, results, &wg) + + go c.pinCheck(t, i, senderPeerId, receiverPeerId, results, &wg) } wg.Wait() + for i := range results { if results[i].Error != nil { - c.log.Error("Error occured", "error", err) - crep.Message = "Error while cheking Token multiple Pins" - return c.l.RenderJSON(req, &crep, http.StatusOK) + return nil, fmt.Errorf("Error while cheking Token multiple Pins for token %v, error : %v", results[i].Token, results[i].Error) } if results[i].Status { - c.log.Error("Token has multiple owners", "token", results[i].Token, "owners", results[i].Owners) - crep.Message = "Token has multiple owners" - return c.l.RenderJSON(req, &crep, http.StatusOK) + return nil, fmt.Errorf("Token %v has multiple owners: %v", results[i].Token, results[i].Owners) } } - //tokenstate check - - tokenStateCheckResult := make([]TokenStateCheckResult, len(sr.TokenInfo)) - for i, ti := range sr.TokenInfo { + tokenStateCheckResult := make([]TokenStateCheckResult, len(tokenInfo)) + for i, ti := range tokenInfo { t := ti.Token wg.Add(1) - go c.checkTokenState(t, did, i, tokenStateCheckResult, &wg, sr.QuorumList, ti.TokenType) + go c.checkTokenState(t, receiverDID, i, tokenStateCheckResult, &wg, quorumList, ti.TokenType) } wg.Wait() for i := range tokenStateCheckResult { if tokenStateCheckResult[i].Error != nil { - c.log.Error("Error occured", "error", err) - crep.Message = "Error while cheking Token State Message : " + tokenStateCheckResult[i].Message - return c.l.RenderJSON(req, &crep, http.StatusOK) + return nil, fmt.Errorf("Error while cheking Token State Message : %v", tokenStateCheckResult[i].Message) } if tokenStateCheckResult[i].Exhausted { c.log.Debug("Token state has been exhausted, Token being Double spent:", tokenStateCheckResult[i].Token) - crep.Message = tokenStateCheckResult[i].Message - return c.l.RenderJSON(req, &crep, http.StatusOK) + return nil, fmt.Errorf("Token state has been exhausted, Token being Double spent: %v, msg: %v", tokenStateCheckResult[i].Token, tokenStateCheckResult[i].Message) } c.log.Debug("Token", tokenStateCheckResult[i].Token, "Message", tokenStateCheckResult[i].Message) } - senderPeerId, _, _ := util.ParseAddress(sr.Address) - err = c.w.TokensReceived(did, sr.TokenInfo, b, senderPeerId, c.peerID) + + err := c.w.TokensReceived(receiverDID, tokenInfo, b, senderPeerId, receiverPeerId) if err != nil { - c.log.Error("Failed to update token status", "err", err) - crep.Message = "Failed to update token status" - return c.l.RenderJSON(req, &crep, http.StatusOK) + return nil, fmt.Errorf("Failed to update token status, error: %v", err) + } + + //add to ipfs to get latest Token State Hash after receiving the token by receiver. The hashes will be returned to sender, and from there to + //quorums using pledgefinality function, to be added to TokenStateHash Table + var updatedtokenhashes []string + var tokenwithtokenhash []string + for _, ti := range tokenInfo { + t := ti.Token + b := c.w.GetLatestTokenBlock(ti.Token, ti.TokenType) + blockId, _ := b.GetBlockID(t) + tokenIDTokenStateData := t + blockId + tokenIDTokenStateBuffer := bytes.NewBuffer([]byte(tokenIDTokenStateData)) + tokenIDTokenStateHash, _ := c.ipfs.Add(tokenIDTokenStateBuffer, ipfsnode.Pin(false), ipfsnode.OnlyHash(true)) + updatedtokenhashes = append(updatedtokenhashes, tokenIDTokenStateHash) + tokenwithtokenhash = append(tokenwithtokenhash, t+"."+tokenIDTokenStateHash) } + + //Updating the latest tokenstatehash with the new owner i.e. receiver + c.w.TokenStateHashUpdate(tokenwithtokenhash) + sc := contract.InitContract(b.GetSmartContract(), nil) if sc == nil { - c.log.Error("Failed to update token status, missing smart contract") - crep.Message = "Failed to update token status, missing smart contract" - return c.l.RenderJSON(req, &crep, http.StatusOK) + return nil, fmt.Errorf("Failed to update token status, missing smart contract") } - bid, err := b.GetBlockID(sr.TokenInfo[0].Token) + + bid, err := b.GetBlockID(tokenInfo[0].Token) if err != nil { - c.log.Error("Failed to update token status, failed to get block ID", "err", err) - crep.Message = "Failed to update token status, failed to get block ID" - return c.l.RenderJSON(req, &crep, http.StatusOK) + return nil, fmt.Errorf("Failed to update token status, failed to get block ID, err: %v", err) + } + + // Only save the transaction details in Transaction history table whenever + // its a general RBT transfer + if sc.GetSenderDID() != sc.GetReceiverDID() { + td := &model.TransactionDetails{ + TransactionID: b.GetTid(), + TransactionType: b.GetTransType(), + BlockID: bid, + Mode: wallet.RecvMode, + Amount: sc.GetTotalRBTs(), + SenderDID: sc.GetSenderDID(), + ReceiverDID: sc.GetReceiverDID(), + Comment: sc.GetComment(), + DateTime: time.Now(), + Status: true, + Epoch: int64(transactionEpoch), + } + c.w.AddTransactionHistory(td) } - td := &wallet.TransactionDetails{ - TransactionID: b.GetTid(), - TransactionType: b.GetTransType(), - BlockID: bid, - Mode: wallet.RecvMode, - Amount: sc.GetTotalRBTs(), - SenderDID: sc.GetSenderDID(), - ReceiverDID: sc.GetReceiverDID(), - Comment: sc.GetComment(), - DateTime: time.Now(), - Status: true, - } - c.w.AddTransactionHistory(td) - crep.Status = true - crep.Message = "Token received successfully" //Adding quorums to DIDPeerTable of receiver - for _, qrm := range sr.QuorumInfo { + for _, qrm := range quorumInfo { c.w.AddDIDPeerMap(qrm.DID, qrm.PeerID, *qrm.DIDType) } + return updatedtokenhashes, nil +} + +func (c *Core) updateReceiverTokenHandle(req *ensweb.Request) *ensweb.Result { + did := c.l.GetQuerry(req, "did") + var sr SendTokenRequest + + err := c.l.ParseJSON(req, &sr) + crep := model.BasicResponse{ + Status: false, + } + if err != nil { + c.log.Error("Failed to parse json request", "err", err) + crep.Message = "Failed to parse json request" + return c.l.RenderJSON(req, &crep, http.StatusOK) + } + + receiverAddress := c.peerID + "." + did + + updatedtokenhashes, err := c.updateReceiverToken( + sr.Address, + receiverAddress, + sr.TokenInfo, + sr.TokenChainBlock, + sr.QuorumList, + sr.QuorumInfo, + sr.TransactionEpoch, + ) + if err != nil { + c.log.Error(err.Error()) + crep.Message = err.Error() + return c.l.RenderJSON(req, &crep, http.StatusOK) + } + + crep.Status = true + crep.Message = "Token received successfully" + crep.Result = updatedtokenhashes return c.l.RenderJSON(req, &crep, http.StatusOK) } @@ -864,16 +879,21 @@ func (c *Core) updatePledgeToken(req *ensweb.Request) *ensweb.Result { } b := block.InitBlock(ur.TokenChainBlock, nil) tks := b.GetTransTokens() + refID := "" + var refIDArr []string = make([]string, 0) if len(tks) > 0 { - id, err := b.GetBlockID(tks[0]) - if err != nil { - c.log.Error("Failed to get block ID") - crep.Message = "Failed to get block ID" - return c.l.RenderJSON(req, &crep, http.StatusOK) + for _, tkn := range tks { + id, err := b.GetBlockID(tkn) + if err != nil { + c.log.Error("Failed to get block ID") + crep.Message = "Failed to get block ID" + return c.l.RenderJSON(req, &crep, http.StatusOK) + } + refIDArr = append(refIDArr, fmt.Sprintf("%v_%v_%v", tkn, b.GetTokenType(tkn), id)) } - refID = fmt.Sprintf("%s,%d,%s", tks[0], b.GetTokenType(tks[0]), id) } + refID = strings.Join(refIDArr, ",") ctcb := make(map[string]*block.Block) tsb := make([]block.TransTokens, 0) @@ -909,6 +929,7 @@ func (c *Core) updatePledgeToken(req *ensweb.Request) *ensweb.Result { } ctcb[t] = lb } + tcb := block.TokenChainBlock{ TransactionType: block.TokenPledgedType, TokenOwner: did, @@ -917,7 +938,9 @@ func (c *Core) updatePledgeToken(req *ensweb.Request) *ensweb.Result { RefID: refID, Tokens: tsb, }, + Epoch: ur.TransactionEpoch, } + nb := block.CreateNewBlock(ctcb, &tcb) if nb == nil { c.log.Error("Failed to create new token chain block - qrm rec") @@ -945,9 +968,14 @@ func (c *Core) updatePledgeToken(req *ensweb.Request) *ensweb.Result { } } - for _, t := range ur.PledgedTokens { - c.up.AddUnPledge(t) + //Adding to the Token State Hash Table + if ur.TransferredTokenStateHashes != nil { + err = c.w.AddTokenStateHash(did, ur.TransferredTokenStateHashes, ur.PledgedTokens, ur.TransactionID) + } + if err != nil { + c.log.Error("Failed to add token state hash", "err", err) } + crep.Status = true crep.Message = "Token pledge status updated" return c.l.RenderJSON(req, &crep, http.StatusOK) @@ -1007,8 +1035,8 @@ func (c *Core) mapDIDArbitration(req *ensweb.Request) *ensweb.Result { } err = c.srv.UpdateTokenDetials(nd) if err != nil { - c.log.Error("Failed to update table detials", "err", err) - br.Message = "Failed to update token detials" + c.log.Error("Failed to update table details", "err", err) + br.Message = "Failed to update token details" return c.l.RenderJSON(req, &br, http.StatusOK) } dm := &service.DIDMap{ @@ -1246,91 +1274,6 @@ func (c *Core) tokenArbitration(req *ensweb.Request) *ensweb.Result { return c.l.RenderJSON(req, &srep, http.StatusOK) } -func (c *Core) getProofverificationDetails(tokenID string, senderAddr string, tknType int) (string, string, error) { - var receiverDID, txnId string - - blk := c.w.GetLatestTokenBlock(tokenID, tknType) - - pbid, err := blk.GetPrevBlockID(tokenID) - if err != nil { - c.log.Error("Failed to get the block id. Unable to verify proof file") - return "", "", err - } - pBlk, err := c.w.GetTokenBlock(tokenID, tknType, pbid) - if err != nil { - c.log.Error("Failed to get the Previous Block Unable to verify proof file") - return "", "", err - } - - prevBlk := block.InitBlock(pBlk, nil) - if prevBlk == nil { - c.log.Error("Failed to initialize the Previous Block Unable to verify proof file") - return "", "", fmt.Errorf("Failed to initilaize previous block") - } - tokenPledgedForDetailsStr := prevBlk.GetTokenPledgedForDetails() - tokenPledgedForDetailsBlkArray := prevBlk.GetTransBlock() - - if tokenPledgedForDetailsStr == "" && tokenPledgedForDetailsBlkArray == nil { - c.log.Error("Failed to get details pledged for token. Unable to verify proof file") - return "", "", fmt.Errorf("Failed to get deatils of pledged for token") - } - - if tokenPledgedForDetailsBlkArray != nil { - tokenPledgedForDetailsBlk := block.InitBlock(tokenPledgedForDetailsBlkArray, nil) - receiverDID = tokenPledgedForDetailsBlk.GetReceiverDID() - txnId = tokenPledgedForDetailsBlk.GetTid() - } - - if tokenPledgedForDetailsStr != "" { - tpfdArray := strings.Split(tokenPledgedForDetailsStr, ",") - - tokenPledgedFor := tpfdArray[0] - tokenPledgedForTypeStr := tpfdArray[1] - tokenPledgedForBlockId := tpfdArray[2] - - tokenPledgedForType, err := strconv.Atoi(tokenPledgedForTypeStr) - if err != nil { - c.log.Error("Failed toconvert to integer", "err", err) - return "", "", err - } - //check if token chain of token pledged for already synced to node - //TODO: Change proof verification method - var pledgedforBlk *block.Block - - pledgedfBlk, err := c.w.GetTokenBlock(tokenPledgedFor, tokenPledgedForType, tokenPledgedForBlockId) - - if err != nil { - c.log.Error("Failed to get the pledged for token's Block Unable to verify proof file, Error: " + err.Error()) - c.log.Debug("Unable get token block from storage..Proceeding for syncing...") - p, err := c.getPeer(senderAddr, "") - if err != nil { - c.log.Error("Failed to get peer", "err", err) - return "", "", err - } - err = c.syncTokenChainFrom(p, tokenPledgedForBlockId, tokenPledgedFor, tokenPledgedForType) - if err != nil { - c.log.Error("Failed to sync token chain block", "err", err) - return "", "", err - } - tcbArray, err := c.w.GetTokenBlock(tokenPledgedFor, tokenPledgedForType, tokenPledgedForBlockId) - if err != nil { - c.log.Error("Failed to fetch previous block", "err", err) - return "", "", err - } - pledgedforBlk = block.InitBlock(tcbArray, nil) - } else if pledgedfBlk != nil { - pledgedforBlk = block.InitBlock(pledgedfBlk, nil) - if pledgedforBlk == nil { - c.log.Error("Failed to initialize the pledged for token's Block Unable to verify proof file") - return "", "", fmt.Errorf("Failed to initilaize previous block") - } - } - receiverDID = pledgedforBlk.GetReceiverDID() - txnId = pledgedforBlk.GetTid() - } - return receiverDID, txnId, nil -} - func (c *Core) unlockTokens(req *ensweb.Request) *ensweb.Result { var tokenList TokenList err := c.l.ParseJSON(req, &tokenList) @@ -1353,3 +1296,16 @@ func (c *Core) unlockTokens(req *ensweb.Request) *ensweb.Result { return c.l.RenderJSON(req, &crep, http.StatusOK) } + +func (c *Core) updateTokenHashDetails(req *ensweb.Request) *ensweb.Result { + c.log.Debug("Updating tokenStateHashDetails in DB") + tokenIDTokenStateHash := c.l.GetQuerry(req, "tokenIDTokenStateHash") + c.log.Debug("tokenIDTokenStateHash from query", tokenIDTokenStateHash) + + err := c.w.RemoveTokenStateHash(tokenIDTokenStateHash) + if err == nil { + fmt.Println("removed hash successfully") + } + return c.l.RenderJSON(req, nil, http.StatusOK) + +} diff --git a/core/quorum_validation.go b/core/quorum_validation.go index f17cd4f5..b7717572 100644 --- a/core/quorum_validation.go +++ b/core/quorum_validation.go @@ -22,6 +22,7 @@ type TokenStateCheckResult struct { Error error Message string tokenIDTokenStateData string + tokenIDTokenStateHash string } func (c *Core) validateSigner(b *block.Block, self_did string, p *ipfsport.Peer) (bool, error) { @@ -339,6 +340,7 @@ func (c *Core) checkTokenState(tokenId, did string, index int, resultArray []Tok //add to ipfs get only the hash of the token+tokenstate tokenIDTokenStateHash, err := c.ipfs.Add(tokenIDTokenStateBuffer, ipfsnode.Pin(false), ipfsnode.OnlyHash(true)) + result.tokenIDTokenStateHash = tokenIDTokenStateHash if err != nil { c.log.Error("Error adding data to ipfs", err) result.Error = err diff --git a/core/self_transfer.go b/core/self_transfer.go new file mode 100644 index 00000000..d9331257 --- /dev/null +++ b/core/self_transfer.go @@ -0,0 +1,250 @@ +package core + +// import ( +// "fmt" +// "net/http" +// "time" + +// "github.com/rubixchain/rubixgoplatform/contract" +// "github.com/rubixchain/rubixgoplatform/core/model" +// "github.com/rubixchain/rubixgoplatform/core/unpledge" +// "github.com/rubixchain/rubixgoplatform/core/wallet" +// "github.com/rubixchain/rubixgoplatform/did" +// "github.com/rubixchain/rubixgoplatform/wrapper/ensweb" + +// "github.com/rubixchain/rubixgoplatform/wrapper/uuid" +// ) + +// func (c *Core) selfTransferService() { +// c.l.AddRoute(APISelfTransfer, "POST", c.APISelfTransfer) +// } + +// func (c *Core) didResponse(req *ensweb.Request, reqID string) *ensweb.Result { +// dc := c.GetWebReq(reqID) +// ch := <-dc.OutChan +// time.Sleep(time.Millisecond * 10) +// sr, ok := ch.(*did.SignResponse) +// if ok { +// return c.l.RenderJSON(req, sr, http.StatusOK) +// } +// br, ok := ch.(*model.BasicResponse) +// if ok { +// c.RemoveWebReq(reqID) +// br.Status = true +// return c.l.RenderJSON(req, br, http.StatusOK) +// } +// return c.l.RenderJSON(req, &model.BasicResponse{Status: false, Message: "Invalid response"}, http.StatusOK) +// } + +// func (c *Core) APISelfTransfer(req *ensweb.Request) *ensweb.Result { +// resp := model.BasicResponse{ +// Status: false, +// } + +// if req.ID == "" { +// c.log.Debug("Request ID for API Self Transfer not set") +// req.ID = uuid.New().String() +// } + +// var selfTransferReq model.SelfTransferRequest +// err := c.l.ParseJSON(req, &selfTransferReq) +// if err != nil { +// return c.l.RenderJSON(req, resp, http.StatusOK) +// } + +// c.AddWebReq(req) +// go c.initSelfTransfer(req.ID, &selfTransferReq) +// return c.didResponse(req, req.ID) +// } + +// func (c *Core) initSelfTransfer(reqID string, req *model.SelfTransferRequest) { +// br := c.selfTransfer(reqID, req) +// dc := c.GetWebReq(reqID) +// if dc == nil { +// c.log.Error("Failed to get did channels") +// return +// } +// dc.OutChan <- br +// } + + +// func (c *Core) selfTransfer(reqID string, rbtTransferRequest *model.RBTTransferRequest) *model.BasicResponse { +// st := time.Now() + +// response := &model.BasicResponse{ +// Status: false, +// } + +// owner := rbtTransferRequest.Sender + +// c.log.Debug("Initiating Self Trasfer for DID: ", owner) + +// // Get all free tokens +// freeTokensOfOwner, err := c.w.GetFreeTokens(owner) +// if err != nil { +// response.Message = "failed to get free tokens of owner, error: " + err.Error() +// return response +// } + +// // Get the transaction epoch for every token and chec +// var selfTransferredTokens []wallet.Token = make([]wallet.Token, 0) + +// for _, token := range freeTokensOfOwner { +// tokenTransactionDetail, err := c.w.GetTransactionDetailsbyTransactionId(token.TransactionID) +// if err != nil { +// return response +// } + +// if time.Now().Unix() - tokenTransactionDetail.Epoch > int64(unpledge.PledgePeriodInSeconds) { +// if err := c.w.LockToken(&token); err != nil { +// errMsg := fmt.Sprintf("selfTransfer: failed to lock tokens %v, exiting selfTransfer routine with error: %v", token.TokenID, err.Error()) +// c.log.Error(errMsg) +// response.Message = errMsg +// return response +// } + +// selfTransferredTokens = append(selfTransferredTokens, token) +// } +// } + + +// // -------------------------------- + +// // Get details of Tokens +// var ownedTokens []wallet.Token +// for _, token := range tokens { +// walletToken, err := c.w.ReadToken(token) +// if err != nil { +// response.Message = err.Error() +// return response +// } +// ownedTokens = append(ownedTokens, *walletToken) +// } +// defer c.w.ReleaseTokens(ownedTokens) + +// c.log.Debug("1") +// // Lock the free tokens for processing +// for _, ownedToken := range ownedTokens { +// if err := c.w.LockToken(&ownedToken); err != nil { +// errMsg := fmt.Sprintf("selfTransfer: failed to lock tokens %v, exiting selfTransfer routine with error: %v", ownedToken.TokenID, err.Error()) +// c.log.Error(errMsg) +// response.Message = errMsg +// return response +// } +// } + +// selfPeerId := c.GetPeerID() +// selfAddress := selfPeerId + "." + ownerDID +// for i := range ownedTokens { +// c.w.Pin(ownedTokens[i].TokenID, wallet.OwnerRole, ownerDID, "TID-Not Generated", selfAddress, selfAddress, ownedTokens[i].TokenValue) +// } + +// c.log.Debug("2") +// // Setup DID +// dc, err := c.SetupDID(reqID, ownerDID) +// if err != nil { +// response.Message = "Failed to setup DID, " + err.Error() +// c.log.Error(fmt.Sprintf("selfTransfer: failed to setup DID, error: %v", err.Error())) +// return response +// } + +// // Create a Contract for the self transfer +// tokenInfos := make([]contract.TokenInfo, 0) +// totalTokenValue := getTotalValueFromTokens(ownedTokens) + +// c.log.Debug("3") +// for _, freeToken := range ownedTokens { +// tokenTypeString := "rbt" +// if freeToken.TokenValue != 1 { +// tokenTypeString = "part" +// } + +// tokenType := c.TokenType(tokenTypeString) +// latestTokenBlock := c.w.GetLatestTokenBlock(freeToken.TokenID, tokenType) +// if latestTokenBlock == nil { +// c.log.Error("failed to get latest block, invalid token chain") +// response.Message = "failed to get latest block, invalid token chain" +// return response +// } + +// latestBlockID, err := latestTokenBlock.GetBlockID(freeToken.TokenID) +// if err != nil { +// c.log.Error("failed to get block id", "err", err) +// response.Message = "failed to get block id, " + err.Error() +// return response +// } +// tokenInfo := contract.TokenInfo{ +// Token: freeToken.TokenID, +// TokenType: tokenType, +// TokenValue: freeToken.TokenValue, +// OwnerDID: freeToken.DID, +// BlockID: latestBlockID, +// } +// tokenInfos = append(tokenInfos, tokenInfo) +// } + +// selfTransferContractType := &contract.ContractType{ +// Type: contract.SCRBTDirectType, +// PledgeMode: contract.POWPledgeMode, +// TotalRBTs: totalTokenValue, +// TransInfo: &contract.TransInfo{ +// SenderDID: ownerDID, +// ReceiverDID: ownerDID, +// Comment: "Self transfer at " + time.Now().String(), +// TransTokens: tokenInfos, +// }, +// ReqID: reqID, +// } + +// selfTransferContract := contract.CreateNewContract(selfTransferContractType) + +// err = selfTransferContract.UpdateSignature(dc) +// if err != nil { +// c.log.Error(err.Error()) +// response.Message = err.Error() +// return response +// } + +// c.log.Debug("5") +// consensusRequest := &ConensusRequest{ +// ReqID: uuid.New().String(), +// Type: 2, // TODO: need to be decided +// SenderPeerID: selfPeerId, +// ReceiverPeerID: selfPeerId, +// ContractBlock: selfTransferContract.GetBlock(), +// } + +// c.log.Debug("6") +// transactionDetails, _, err := c.initiateConsensus(consensusRequest, selfTransferContract, dc) +// if err != nil { +// c.log.Error("Consensus failed ", "err", err) +// response.Message = "Consensus failed " + err.Error() +// return response +// } +// transactionDetails.Amount = totalTokenValue +// et := time.Now() +// dif := et.Sub(st) +// transactionDetails.TotalTime = float64(dif.Milliseconds()) + +// // if err := c.w.AddTransactionHistory(transactionDetails); err != nil { +// // errMsg := fmt.Sprintf("Error occured while adding transaction details: %v", err) +// // c.log.Error(errMsg) +// // response.Message = errMsg +// // return response +// // } + +// c.log.Info("Self Transfer finished successfully", "duration", dif, " trnxid", transactionDetails.TransactionID) +// response.Status = true + +// return response +// } + +// // func getTotalValueFromTokens(tokens []wallet.Token) float64 { +// // var totatValue float64 = 0.0 + +// // for _, token := range tokens { +// // totatValue += token.TokenValue +// // } + +// // return totatValue +// // } \ No newline at end of file diff --git a/core/smart_contract_token_operations.go b/core/smart_contract_token_operations.go index c21c2f34..fd3edf9d 100644 --- a/core/smart_contract_token_operations.go +++ b/core/smart_contract_token_operations.go @@ -28,6 +28,8 @@ func (c *Core) DeploySmartContractToken(reqID string, deployReq *model.DeploySma */ func (c *Core) deploySmartContractToken(reqID string, deployReq *model.DeploySmartContractRequest) *model.BasicResponse { st := time.Now() + txEpoch := int(st.Unix()) + resp := &model.BasicResponse{ Status: false, } @@ -105,7 +107,7 @@ func (c *Core) deploySmartContractToken(reqID string, deployReq *model.DeploySma consensusContractDetails := &contract.ContractType{ Type: contract.SmartContractDeployType, - PledgeMode: contract.POWPledgeMode, + PledgeMode: contract.PeriodicPledgeMode, TotalRBTs: deployReq.RBTAmount, TransInfo: &contract.TransInfo{ DeployerDID: did, @@ -142,6 +144,7 @@ func (c *Core) deploySmartContractToken(reqID string, deployReq *model.DeploySma ContractBlock: consensusContract.GetBlock(), SmartContractToken: deployReq.SmartContractToken, Mode: SmartContractDeployMode, + TransactionEpoch: txEpoch, } txnDetails, _, err := c.initiateConsensus(conensusRequest, consensusContract, didCryptoLib) @@ -189,6 +192,8 @@ func (c *Core) ExecuteSmartContractToken(reqID string, executeReq *model.Execute func (c *Core) executeSmartContractToken(reqID string, executeReq *model.ExecuteSmartContractRequest) *model.BasicResponse { st := time.Now() + txEpoch := int(st.Unix()) + resp := &model.BasicResponse{ Status: false, } @@ -245,7 +250,7 @@ func (c *Core) executeSmartContractToken(reqID string, executeReq *model.Execute //create teh consensuscontract consensusContractDetails := &contract.ContractType{ Type: contract.SmartContractDeployType, - PledgeMode: contract.POWPledgeMode, + PledgeMode: contract.PeriodicPledgeMode, TotalRBTs: smartContractValue, TransInfo: &contract.TransInfo{ ExecutorDID: did, @@ -283,6 +288,7 @@ func (c *Core) executeSmartContractToken(reqID string, executeReq *model.Execute ContractBlock: consensusContract.GetBlock(), SmartContractToken: executeReq.SmartContractToken, Mode: SmartContractExecuteMode, + TransactionEpoch: txEpoch, } txnDetails, _, err := c.initiateConsensus(conensusRequest, consensusContract, didCryptoLib) diff --git a/core/token.go b/core/token.go index f031727e..2d757b43 100644 --- a/core/token.go +++ b/core/token.go @@ -51,39 +51,39 @@ func (c *Core) GetAllTokens(did string, tt string) (*model.TokenResponse, error) if err != nil { return tr, nil } - tr.TokenDetials = make([]model.TokenDetial, 0) + tr.TokenDetails = make([]model.TokenDetail, 0) for _, t := range tkns { - td := model.TokenDetial{ + td := model.TokenDetail{ Token: t.TokenID, Status: t.TokenStatus, } - tr.TokenDetials = append(tr.TokenDetials, td) + tr.TokenDetails = append(tr.TokenDetails, td) } case model.DTType: tkns, err := c.w.GetAllDataTokens(did) if err != nil { return tr, nil } - tr.TokenDetials = make([]model.TokenDetial, 0) + tr.TokenDetails = make([]model.TokenDetail, 0) for _, t := range tkns { - td := model.TokenDetial{ + td := model.TokenDetail{ Token: t.TokenID, Status: t.TokenStatus, } - tr.TokenDetials = append(tr.TokenDetials, td) + tr.TokenDetails = append(tr.TokenDetails, td) } case model.NFTType: tkns := c.w.GetAllNFT(did) if tkns == nil { return tr, nil } - tr.TokenDetials = make([]model.TokenDetial, 0) + tr.TokenDetails = make([]model.TokenDetail, 0) for _, t := range tkns { - td := model.TokenDetial{ + td := model.TokenDetail{ Token: t.TokenID, Status: t.TokenStatus, } - tr.TokenDetials = append(tr.TokenDetials, td) + tr.TokenDetails = append(tr.TokenDetails, td) } default: tr.BasicResponse.Status = false @@ -490,3 +490,29 @@ func (c *Core) GetRequiredTokens(did string, txnAmount float64) ([]wallet.Token, remainingAmount = floatPrecision(remainingAmount, MaxDecimalPlaces) return requiredTokens, remainingAmount, nil } + +func (c *Core) GetPledgedInfo() ([]model.PledgedTokenStateDetails, error) { + wt, err := c.w.GetAllTokenStateHash() + if err != nil && err.Error() != "no records found" { + c.log.Error("Failed to get token state hashes", "err", err) + return []model.PledgedTokenStateDetails{}, fmt.Errorf("failed to get token states") + } + info := []model.PledgedTokenStateDetails{} + for _, t := range wt { + k := model.PledgedTokenStateDetails{ + DID: t.DID, + TokensPledged: t.PledgedTokens, + TokenStateHash: t.TokenStateHash, + } + info = append(info, k) + } + return info, nil +} + +func (c *Core) UpdatePledgedTokenInfo(tokenstatehash string) error { + err := c.w.RemoveTokenStateHash(tokenstatehash) + if err != nil && err.Error() != "no records found" { + c.log.Error("Failed to get token state hash", "err", err) + } + return nil +} diff --git a/core/transfer.go b/core/transfer.go index b65a231c..95e6db5a 100644 --- a/core/transfer.go +++ b/core/transfer.go @@ -8,7 +8,9 @@ import ( "github.com/rubixchain/rubixgoplatform/contract" "github.com/rubixchain/rubixgoplatform/core/model" + "github.com/rubixchain/rubixgoplatform/core/unpledge" "github.com/rubixchain/rubixgoplatform/core/wallet" + "github.com/rubixchain/rubixgoplatform/did" "github.com/rubixchain/rubixgoplatform/wrapper/uuid" ) @@ -22,94 +24,181 @@ func (c *Core) InitiateRBTTransfer(reqID string, req *model.RBTTransferRequest) dc.OutChan <- br } -func (c *Core) initiateRBTTransfer(reqID string, req *model.RBTTransferRequest) *model.BasicResponse { - st := time.Now() - resp := &model.BasicResponse{ - Status: false, - } - if req.Sender == req.Receiver { - resp.Message = "Sender and receiver cannot be same" - return resp - } - did := req.Sender - rdid := req.Receiver - rpeerid := c.w.GetPeerID(rdid) - if rpeerid == "" { - c.log.Error("Peer ID not found", "did", rdid) - resp.Message = "invalid address, Peer ID not found" - return resp - } +func gatherTokensForTransaction(c *Core, req *model.RBTTransferRequest, dc did.DIDCrypto, isSelfRBTTransfer bool) ([]wallet.Token, error) { + var tokensForTransfer []wallet.Token - if req.TokenCount < MinTrnxAmt { - resp.Message = "Input transaction amount is less than minimum transaction amount" - return resp - } + senderDID := req.Sender - decimalPlaces := strconv.FormatFloat(req.TokenCount, 'f', -1, 64) - decimalPlacesStr := strings.Split(decimalPlaces, ".") - if len(decimalPlacesStr) == 2 && len(decimalPlacesStr[1]) > MaxDecimalPlaces { - c.log.Error("Transaction amount exceeds %d decimal places.\n", MaxDecimalPlaces) - resp.Message = fmt.Sprintf("Transaction amount exceeds %d decimal places.\n", MaxDecimalPlaces) - return resp - } + if !isSelfRBTTransfer { + if req.TokenCount < MinTrnxAmt { + return nil, fmt.Errorf("input transaction amount is less than minimum transaction amount") + } + + decimalPlaces := strconv.FormatFloat(req.TokenCount, 'f', -1, 64) + decimalPlacesStr := strings.Split(decimalPlaces, ".") + if len(decimalPlacesStr) == 2 && len(decimalPlacesStr[1]) > MaxDecimalPlaces { + return nil, fmt.Errorf("transaction amount exceeds %v decimal places", MaxDecimalPlaces) + } + + accountBalance, err := c.GetAccountInfo(senderDID) + if err != nil { + return nil, fmt.Errorf("insufficient tokens or tokens are locked or %v", err.Error()) + } else { + if req.TokenCount > accountBalance.RBTAmount { + return nil, fmt.Errorf("insufficient balance, account balance is %v, trnx value is %v", accountBalance.RBTAmount, req.TokenCount) + } + } + + reqTokens, remainingAmount, err := c.GetRequiredTokens(senderDID, req.TokenCount) + if err != nil { + c.w.ReleaseTokens(reqTokens) + return nil, fmt.Errorf("insufficient tokens or tokens are locked or %v", err.Error()) + } - dc, err := c.SetupDID(reqID, did) - if err != nil { - resp.Message = "Failed to setup DID, " + err.Error() - return resp + if len(reqTokens) != 0 { + tokensForTransfer = append(tokensForTransfer, reqTokens...) + } + //check if ther is enough tokens to do transfer + // Get the required tokens from the DID bank + // this method locks the token needs to be released or + // removed once it done with the transfer + if remainingAmount > 0 { + wt, err := c.GetTokens(dc, senderDID, remainingAmount) + if err != nil { + return nil, fmt.Errorf("insufficient tokens or tokens are locked or %v", err.Error()) + } + if len(wt) != 0 { + tokensForTransfer = append(tokensForTransfer, wt...) + } + } + + var sumOfTokensForTxn float64 + for _, tokenForTransfer := range tokensForTransfer { + sumOfTokensForTxn = sumOfTokensForTxn + tokenForTransfer.TokenValue + sumOfTokensForTxn = floatPrecision(sumOfTokensForTxn, MaxDecimalPlaces) + } + + if sumOfTokensForTxn != req.TokenCount { + return nil, fmt.Errorf("sum of Selected Tokens sum : %v is not equal to trnx value : %v", sumOfTokensForTxn, req.TokenCount) + } + + return tokensForTransfer, nil + } else { + // Get all free tokens + tokensOwnedBySender, err := c.w.GetFreeTokens(senderDID) + if err != nil { + if strings.Contains(err.Error(), "no records found") { + return []wallet.Token{}, nil + } + return nil, fmt.Errorf("failed to get free tokens of owner, error: %v", err.Error()) + } + + // Get the transaction epoch for every token and chec + for _, token := range tokensOwnedBySender { + tokenTransactionDetail, err := c.w.GetTransactionDetailsbyTransactionId(token.TransactionID) + if err != nil { + return nil, fmt.Errorf("failed to get transaction details for trx hash: %v, err: %v", token.TransactionID, err) + } + + if time.Now().Unix() - tokenTransactionDetail.Epoch > int64(unpledge.PledgePeriodInSeconds) { + if err := c.w.LockToken(&token); err != nil { + return nil, fmt.Errorf("failed to lock tokens %v, exiting selfTransfer routine with error: %v", token.TokenID, err.Error()) + } + + tokensForTransfer = append(tokensForTransfer, token) + } + } + + c.log.Debug("Tokens acquired for self transfer") + return tokensForTransfer, nil } +} - accountBalance, err := c.GetAccountInfo(did) - if err != nil { - c.log.Error("Failed to get tokens", "err", err) - resp.Message = "Insufficient tokens or tokens are locked or " + err.Error() - return resp +func getContractType(reqID string, req *model.RBTTransferRequest, transTokenInfo []contract.TokenInfo, isSelfRBTTransfer bool) *contract.ContractType { + if !isSelfRBTTransfer { + return &contract.ContractType{ + Type: contract.SCRBTDirectType, + PledgeMode: contract.PeriodicPledgeMode, + TotalRBTs: req.TokenCount, + TransInfo: &contract.TransInfo{ + SenderDID: req.Sender, + ReceiverDID: req.Receiver, + Comment: req.Comment, + TransTokens: transTokenInfo, + }, + ReqID: reqID, + } } else { - if req.TokenCount > accountBalance.RBTAmount { - c.log.Error(fmt.Sprint("Insufficient balance, account balance is ", accountBalance.RBTAmount, " trnx value is ", req.TokenCount)) - resp.Message = fmt.Sprint("Insufficient balance, account balance is ", accountBalance.RBTAmount, " trnx value is ", req.TokenCount) - return resp + // Calculate the total value of self transfer RBT tokens + var totalRBTValue float64 + for _, tokenInfo := range transTokenInfo { + totalRBTValue += tokenInfo.TokenValue } + + return &contract.ContractType{ + Type: contract.SCRBTDirectType, + PledgeMode: contract.PeriodicPledgeMode, + TotalRBTs: totalRBTValue, + TransInfo: &contract.TransInfo{ + SenderDID: req.Sender, + ReceiverDID: req.Receiver, + Comment: "Self Transfer at " + time.Now().String(), + TransTokens: transTokenInfo, + }, + ReqID: reqID, + } + } +} + +func getConsensusRequest(consensusRequestType int, senderPeerID string, receiverPeerID string, contractBlock []byte, transactionEpoch int, isSelfTransfer bool) *ConensusRequest { + var consensusRequest *ConensusRequest = &ConensusRequest{ + ReqID: uuid.New().String(), + Type: consensusRequestType, + SenderPeerID: senderPeerID, + ReceiverPeerID: receiverPeerID, + ContractBlock: contractBlock, + TransactionEpoch: transactionEpoch, + } + + if isSelfTransfer { + consensusRequest.Mode = SelfTransferMode } - tokensForTxn := make([]wallet.Token, 0) + return consensusRequest +} + +func (c *Core) initiateRBTTransfer(reqID string, req *model.RBTTransferRequest) *model.BasicResponse { + st := time.Now() + txEpoch := int(st.Unix()) + + resp := &model.BasicResponse{ + Status: false, + } - reqTokens, remainingAmount, err := c.GetRequiredTokens(did, req.TokenCount) + senderDID := req.Sender + receiverdid := req.Receiver + + // This flag indicates if the call is made for Self Transfer or general token transfer + isSelfRBTTransfer := senderDID == receiverdid + + dc, err := c.SetupDID(reqID, senderDID) if err != nil { - c.w.ReleaseTokens(reqTokens) - c.log.Error("Failed to get tokens", "err", err) - resp.Message = "Insufficient tokens or tokens are locked or " + err.Error() + resp.Message = "Failed to setup DID, " + err.Error() return resp } - if len(reqTokens) != 0 { - tokensForTxn = append(tokensForTxn, reqTokens...) - } - //check if ther is enough tokens to do transfer - // Get the required tokens from the DID bank - // this method locks the token needs to be released or - // removed once it done with the transfer - if remainingAmount > 0 { - wt, err := c.GetTokens(dc, did, remainingAmount) - if err != nil { - c.log.Error("Failed to get tokens", "err", err) - resp.Message = "Insufficient tokens or tokens are locked" - return resp - } - if len(wt) != 0 { - tokensForTxn = append(tokensForTxn, wt...) - } - } - var sumOfTokensForTxn float64 - for _, tokenForTxn := range tokensForTxn { - sumOfTokensForTxn = sumOfTokensForTxn + tokenForTxn.TokenValue - sumOfTokensForTxn = floatPrecision(sumOfTokensForTxn, MaxDecimalPlaces) + tokensForTxn, err := gatherTokensForTransaction(c, req, dc, isSelfRBTTransfer) + if err != nil { + c.log.Error(err.Error()) + resp.Message = err.Error() + return resp } - if sumOfTokensForTxn != req.TokenCount { - c.log.Error(fmt.Sprint("Sum of Selected Tokens sum : ", sumOfTokensForTxn, " is not equal to trnx value : ", req.TokenCount)) - resp.Message = fmt.Sprint("Sum of Selected Tokens sum : ", sumOfTokensForTxn, " is not equal to trnx value : ", req.TokenCount) + // In case of self transfer + if len(tokensForTxn) == 0 && isSelfRBTTransfer { + resp.Status = true + resp.Message = "No tokens present for self transfer" return resp } @@ -117,16 +206,27 @@ func (c *Core) initiateRBTTransfer(reqID string, req *model.RBTTransferRequest) defer c.w.ReleaseTokens(tokensForTxn) for i := range tokensForTxn { - c.w.Pin(tokensForTxn[i].TokenID, wallet.OwnerRole, did, "TID-Not Generated", req.Sender, req.Receiver, tokensForTxn[i].TokenValue) + c.w.Pin(tokensForTxn[i].TokenID, wallet.OwnerRole, senderDID, "TID-Not Generated", req.Sender, req.Receiver, tokensForTxn[i].TokenValue) } // Get the receiver & do sanity check - p, err := c.getPeer(req.Receiver, did) - if err != nil { - resp.Message = "Failed to get receiver peer, " + err.Error() - return resp + var rpeerid string = "" + if !isSelfRBTTransfer { + rpeerid := c.w.GetPeerID(receiverdid) + if rpeerid == "" { + c.log.Error("Peer ID not found", "did", receiverdid) + resp.Message = "invalid address, Peer ID not found" + return resp + } + + p, err := c.getPeer(req.Receiver, senderDID) + if err != nil { + resp.Message = "Failed to get receiver peer, " + err.Error() + return resp + } + defer p.Close() } - defer p.Close() + wta := make([]string, 0) for i := range tokensForTxn { wta = append(wta, tokensForTxn[i].TokenID) @@ -145,6 +245,7 @@ func (c *Core) initiateRBTTransfer(reqID string, req *model.RBTTransferRequest) resp.Message = "failed to get latest block, invalid token chain" return resp } + bid, err := blk.GetBlockID(tokensForTxn[i].TokenID) if err != nil { c.log.Error("failed to get block id", "err", err) @@ -160,32 +261,19 @@ func (c *Core) initiateRBTTransfer(reqID string, req *model.RBTTransferRequest) } tis = append(tis, ti) } - sct := &contract.ContractType{ - Type: contract.SCRBTDirectType, - PledgeMode: contract.POWPledgeMode, - TotalRBTs: req.TokenCount, - TransInfo: &contract.TransInfo{ - SenderDID: did, - ReceiverDID: rdid, - Comment: req.Comment, - TransTokens: tis, - }, - ReqID: reqID, - } - sc := contract.CreateNewContract(sct) + + contractType := getContractType(reqID, req, tis, isSelfRBTTransfer) + sc := contract.CreateNewContract(contractType) + err = sc.UpdateSignature(dc) if err != nil { c.log.Error(err.Error()) resp.Message = err.Error() return resp } - cr := &ConensusRequest{ - ReqID: uuid.New().String(), - Type: req.Type, - SenderPeerID: c.peerID, - ReceiverPeerID: rpeerid, - ContractBlock: sc.GetBlock(), - } + + cr := getConsensusRequest(req.Type, c.peerID, rpeerid, sc.GetBlock(), txEpoch, isSelfRBTTransfer) + td, _, err := c.initiateConsensus(cr, sc, dc) if err != nil { c.log.Error("Consensus failed ", "err", err) @@ -196,7 +284,14 @@ func (c *Core) initiateRBTTransfer(reqID string, req *model.RBTTransferRequest) dif := et.Sub(st) td.Amount = req.TokenCount td.TotalTime = float64(dif.Milliseconds()) - c.w.AddTransactionHistory(td) + + if err := c.w.AddTransactionHistory(td); err != nil { + errMsg := fmt.Sprintf("Error occured while adding transaction details: %v", err) + c.log.Error(errMsg) + resp.Message = errMsg + return resp + } + /* blockHash, err := extractHash(td.BlockID) if err != nil { c.log.Error("Consensus failed", "err", err) @@ -205,8 +300,8 @@ func (c *Core) initiateRBTTransfer(reqID string, req *model.RBTTransferRequest) } */ etrans := &ExplorerTrans{ TID: td.TransactionID, - SenderDID: did, - ReceiverDID: rdid, + SenderDID: senderDID, + ReceiverDID: receiverdid, Amount: req.TokenCount, TrasnType: req.Type, TokenIDs: wta, diff --git a/core/txndetails.go b/core/txndetails.go index 91b15be9..e7a64d17 100644 --- a/core/txndetails.go +++ b/core/txndetails.go @@ -4,11 +4,11 @@ import ( "strings" "time" - "github.com/rubixchain/rubixgoplatform/core/wallet" + "github.com/rubixchain/rubixgoplatform/core/model" ) -func (c *Core) GetTxnDetailsByID(txnID string) (wallet.TransactionDetails, error) { - var th wallet.TransactionDetails +func (c *Core) GetTxnDetailsByID(txnID string) (model.TransactionDetails, error) { + var th model.TransactionDetails res, err := c.w.GetTransactionDetailsbyTransactionId(txnID) if err != nil { return th, err @@ -16,12 +16,12 @@ func (c *Core) GetTxnDetailsByID(txnID string) (wallet.TransactionDetails, error return res, nil } -func (c *Core) GetTxnDetailsByDID(did string, role string, startDateStr string, endDateStr string) ([]wallet.TransactionDetails, error) { +func (c *Core) GetTxnDetailsByDID(did string, role string, startDateStr string, endDateStr string) ([]model.TransactionDetails, error) { var startDate time.Time var endDate time.Time var err error - var result []wallet.TransactionDetails + var result []model.TransactionDetails if role == "" { result, err = c.w.GetTransactionByDID(did) @@ -80,7 +80,7 @@ func (c *Core) GetTxnDetailsByDID(did string, role string, startDateStr string, return nil, nil } -func (c *Core) GetTxnDetailsByComment(comment string) ([]wallet.TransactionDetails, error) { +func (c *Core) GetTxnDetailsByComment(comment string) ([]model.TransactionDetails, error) { res, err := c.w.GetTransactionByComment(comment) if err != nil { return nil, err @@ -89,8 +89,8 @@ func (c *Core) GetTxnDetailsByComment(comment string) ([]wallet.TransactionDetai } // FilterTxnDetailsByDateRange filters TransactionDetails by a date range. -func (c *Core) FilterTxnDetailsByDateRange(transactions []wallet.TransactionDetails, startDate time.Time, endDate time.Time) ([]wallet.TransactionDetails, error) { - var filteredTransactions []wallet.TransactionDetails +func (c *Core) FilterTxnDetailsByDateRange(transactions []model.TransactionDetails, startDate time.Time, endDate time.Time) ([]model.TransactionDetails, error) { + var filteredTransactions []model.TransactionDetails for _, txn := range transactions { txnDateTimeStr := txn.DateTime.Format("2006-01-02") txnDateTimeParsed, err := time.Parse("2006-01-02", txnDateTimeStr) @@ -105,8 +105,8 @@ func (c *Core) FilterTxnDetailsByDateRange(transactions []wallet.TransactionDeta return filteredTransactions, nil } -func (c *Core) GetCountofTxn(did string) (wallet.TransactionCount, error) { - result := wallet.TransactionCount{ +func (c *Core) GetCountofTxn(did string) (model.TransactionCount, error) { + result := model.TransactionCount{ DID: did, } txnAsSender, err := c.w.GetTransactionBySender(did) diff --git a/core/unpledge.go b/core/unpledge.go index 388a6662..a04d8b6f 100644 --- a/core/unpledge.go +++ b/core/unpledge.go @@ -1,94 +1,394 @@ package core import ( + "encoding/base64" + "encoding/json" + "errors" "fmt" - "os" + "strings" "time" "github.com/rubixchain/rubixgoplatform/block" - "github.com/rubixchain/rubixgoplatform/token" + "github.com/rubixchain/rubixgoplatform/core/wallet" + + // "github.com/rubixchain/rubixgoplatform/core/model" + tkn "github.com/rubixchain/rubixgoplatform/token" ) -func (c *Core) Unpledge(t string, file string) error { - unpledgetokendetails, err := c.w.ReadToken(t) +const UnpledgeQueueTable string = "unpledgequeue" +const pledgePeriodInSeconds int = 100 //7 * 24 * 60 * 60 + +type TransTokenBlock struct { + TokenID string `json:"token_id"` + TransferBlock string `json:"token_block"` +} + +type PledgeUnpledgeBlock struct { + TokenID string `json:"token_id"` + PledgeBlock string `json:"pledge_block"` + UnpledgeBlock string `json:"unpledge_block"` +} + +type PledgeInformation struct { + TokenID string `json:"token_id"` + TokenType int `json:"token_type"` + PledgeBlockID string `json:"pledge_block_id"` + UnpledgeBlockID string `json:"unpledge_block_id"` + QuorumDID string `json:"quorum_did"` + TransactionID string `json:"transaction_id"` +} + +type UnpledgeQueueInfo struct { + TransactionID string `gorm:"column:tx_id;primaryKey"` + PledgeTokens string `gorm:"column:pledge_tokens"` + Epoch int64 `gorm:"column:epoch"` + QuorumDID string `gorm:"column:quorum_did"` +} + +func (c *Core) InititateUnpledgeProcess() error { + // Get the list of transactions from the unpledgeQueue table + var UnpledgeQueueInfoList []UnpledgeQueueInfo + err := c.s.Read(UnpledgeQueueTable, &UnpledgeQueueInfoList, "tx_id != ?", "") if err != nil { - c.log.Error("Failed to fetch unpledge token details fot token ", t, " error : ", err) - } - var tokenType int - if c.testNet { - if unpledgetokendetails.TokenValue == 1 { - tokenType = token.TestTokenType - } else if unpledgetokendetails.TokenValue < 1 { - tokenType = token.TestPartTokenType - } - } else { - if unpledgetokendetails.TokenValue == 1 { - tokenType = token.RBTTokenType - } else if unpledgetokendetails.TokenValue < 1 { - tokenType = token.PartTokenType + if strings.Contains(err.Error(), "no records found") { + c.log.Info("No tokens left to unpledge") + } else { + return err } } - b := c.w.GetLatestTokenBlock(t, tokenType) - if b == nil { - c.log.Error("Failed to unpledge invalid tokne chain block for token ", t, " having token type as ", tokenType) - return fmt.Errorf("Failed to unpledge invalid tokne chain block for token ", t, " having token type as ", tokenType) - } - f, err := os.Open(file) - if err != nil { - c.log.Error("Failed to unpledge, unable to open file", "err", err) - return err + + var pledgeInformation []*PledgeInformation + + for _, info := range UnpledgeQueueInfoList { + var readyToUnpledge bool = false + + // Get all the token hashes by their transaction ID. + // If there are no records found, that means all the tokens have changed their token, initiate unpledge + // Else check if the pledging period has passed for all tokens, if yes, then unpledge. Else wait for the CheckPeriod + tokenStateHashDetails, err := c.w.GetTokenStateHashByTransactionID(info.TransactionID) + if err != nil { + c.log.Error(fmt.Sprintf("error occured while fetching token state hashes for transaction ID: %v", info.TransactionID)) + return err + } + + // Not all tokens have undergone state change + if len(tokenStateHashDetails) > 0 { + // check if pledging period has passed or not + currentTimeEpoch := time.Now().Unix() + transactionEpoch := info.Epoch + + if (currentTimeEpoch - transactionEpoch) > int64(pledgePeriodInSeconds) { + readyToUnpledge = true + c.log.Debug("Tokens have gone past their pledge duration. Proceeding to unpledge...") + } + } else { + readyToUnpledge = true + c.log.Debug("All tokens have undergone state chanage. Proceeding to unpledge...") + + } + + if readyToUnpledge { + pledgeInformation, err = unpledgeAllTokens(c, info.TransactionID, info.PledgeTokens, info.QuorumDID) + if err != nil { + c.log.Error(fmt.Sprintf("failed while unpledging tokens for transaction: %v", info.TransactionID)) + return err + } + + creditStorageErr := storeCredit(c, info.TransactionID, info.QuorumDID, pledgeInformation) + if creditStorageErr != nil { + c.log.Error(fmt.Sprintf("failed while storing credits, err: %v", creditStorageErr.Error())) + return err + } + + c.s.Delete(UnpledgeQueueTable, &UnpledgeQueueInfo{}, "tx_id = ?", info.TransactionID) + c.log.Info(fmt.Sprintf("Unpledging for tx %v are successful. Credits have been awarded", info.TransactionID)) + } } - id, err := c.ipfs.Add(f) + + return nil +} + +func storeCredit(c *Core, txID string, quorumDID string, pledgeInfo []*PledgeInformation) error { + pledgeInfoBytes, err := json.Marshal(pledgeInfo) if err != nil { - f.Close() - c.log.Error("Failed to add file to ipfs", "err", err) - return err + return fmt.Errorf("failed while marshalling credits: %v", err.Error()) } - f.Close() - os.Remove(file) - ctcb := make(map[string]*block.Block) - tsb := make([]block.TransTokens, 0) - - ts := block.TransTokens{ - Token: t, - TokenType: tokenType, - UnplededID: id, - } - did := b.GetOwner() - dc, ok := c.qc[did] - if !ok { - c.log.Error("Failed to get quorum did crypto") - return fmt.Errorf("failed to get quorum did crypto") + pledgeInfoEncoded := base64.StdEncoding.EncodeToString(pledgeInfoBytes) + + credit := &wallet.Credit{ + DID: quorumDID, + Credit: pledgeInfoEncoded, + Tx: txID, } - tsb = append(tsb, ts) - ctcb[t] = b - tcb := block.TokenChainBlock{ - TransactionType: block.TokenUnpledgedType, - TokenOwner: did, - TransInfo: &block.TransInfo{ - Comment: "Token is un pledged at " + time.Now().String(), - Tokens: tsb, - }, + + return c.s.Write(wallet.CreditStorage, credit) +} + +func unpledgeAllTokens(c *Core, transactionID string, pledgeTokens string, quorumDID string) ([]*PledgeInformation, error) { + c.log.Debug(fmt.Sprintf("Executing Callback for tx for unpledging: %v", transactionID)) + + var pledgeInfoList []*PledgeInformation = make([]*PledgeInformation, 0) + pledgeTokensList := strings.Split(pledgeTokens, ",") + + if len(pledgeTokensList) == 0 { + return nil, fmt.Errorf("expected atleast one pledged token for unpledging") } - nb := block.CreateNewBlock(ctcb, &tcb) - if nb == nil { - c.log.Error("Failed to create new token chain block") - return fmt.Errorf("failed to create new token chain block") + + for _, pledgeToken := range pledgeTokensList { + var tokenValue float64 + var tokenType int + + // Read Token from token hash + walletToken, err := c.w.ReadToken(pledgeToken) + if err != nil { + return nil, err + } + tokenValue = walletToken.TokenValue + + c.log.Debug(fmt.Sprintf("Tx: %v, Status of pledge token %v is %v", transactionID, pledgeToken, walletToken.TokenStatus)) + + if c.testNet { + if tokenValue == 1 { + tokenType = tkn.TestTokenType + } else if tokenValue < 1 { + tokenType = tkn.TestPartTokenType + } + } else { + if tokenValue == 1 { + tokenType = tkn.RBTTokenType + } else if tokenValue < 1 { + tokenType = tkn.PartTokenType + } + } + + b := c.w.GetLatestTokenBlock(pledgeToken, tokenType) + if b == nil { + c.log.Error("Failed to unpledge invalid tokne chain block for token ", pledgeToken, " having token type as ", tokenType) + return nil, fmt.Errorf("Failed to unpledge invalid tokne chain block for token ", pledgeToken, " having token type as ", tokenType) + } + + if b.GetTransType() != block.TokenPledgedType { + c.log.Error(fmt.Sprintf("failed while unpledging token %v, token must be in pledged state before unpledging", pledgeToken)) + return nil, fmt.Errorf("failed while unpledging token %v, token must be in pledged state before unpledging", pledgeToken) + } + + pledgeTokenBlockID, err := b.GetBlockID(pledgeToken) + if err != nil { + errMsg := fmt.Sprintf("failed while unpledging token %v, unable to fetch block ID", pledgeToken) + c.log.Error(errMsg) + return nil, errors.New(errMsg) + } + + ctcb := make(map[string]*block.Block) + tsb := make([]block.TransTokens, 0) + + ts := block.TransTokens{ + Token: pledgeToken, + TokenType: tokenType, + } + + dc, ok := c.qc[quorumDID] + if !ok { + c.log.Error("Failed to get quorum did crypto") + return nil, fmt.Errorf("failed to get quorum did crypto") + } + tsb = append(tsb, ts) + ctcb[pledgeToken] = b + currentTime := time.Now() + + tcb := block.TokenChainBlock{ + TransactionType: block.TokenUnpledgedType, + TokenOwner: quorumDID, + TransInfo: &block.TransInfo{ + Comment: "Token is un pledged at " + currentTime.String(), + Tokens: tsb, + }, + Epoch: int(currentTime.Unix()), + } + + nb := block.CreateNewBlock(ctcb, &tcb) + if nb == nil { + c.log.Error("Failed to create new token chain block") + return nil, fmt.Errorf("failed to create new token chain block") + } + + err = nb.UpdateSignature(dc) + if err != nil { + c.log.Error("Failed to update the signature", "err", err) + return nil, fmt.Errorf("failed to update the signature") + } + + err = c.w.CreateTokenBlock(nb) + if err != nil { + c.log.Error("Failed to update token chain block", "err", err) + return nil, err + } + + err = c.w.UnpledgeWholeToken(quorumDID, pledgeToken, tokenType) + if err != nil { + c.log.Error("Failed to update un pledge token", "err", err) + return nil, err + } + + unpledgeTokenBlockID, err := nb.GetBlockID(pledgeToken) + if err != nil { + errMsg := fmt.Sprintf("failed while unpledging token %v, unable to fetch block ID", pledgeToken) + c.log.Error(errMsg) + return nil, errors.New(errMsg) + } + + // Add pledge and unpledge block information of a Pledged token + pledgeInfoList = append(pledgeInfoList, &PledgeInformation{ + TokenID: pledgeToken, + TokenType: tokenType, + PledgeBlockID: pledgeTokenBlockID, + UnpledgeBlockID: unpledgeTokenBlockID, + QuorumDID: quorumDID, + TransactionID: transactionID, + }) } - err = nb.UpdateSignature(dc) + + // If the unpledging is happening after the pledging period, we can safely remove + // the TokenStateHash table records for the input transactionID + err := c.w.RemoveTokenStateHashByTransactionID(transactionID) if err != nil { - c.log.Error("Failed to update the signature", "err", err) - return fmt.Errorf("failed to update the signature") + return nil, err } - err = c.w.CreateTokenBlock(nb) - if err != nil { - c.log.Error("Failed to update token chain block", "err", err) - return err + + return pledgeInfoList, nil +} + +// type UnpledgeCBType func(transactionID string, pledgeTokens string, quorumDID string) ([]*PledgeInformation, error) +func (c *Core) ExecuteUnpledge(transactionID string, pledgeTokens string, quorumDID string) ([]*PledgeInformation, error) { + c.log.Debug(fmt.Sprintf("Executing Callback for tx for unpledging: %v", transactionID)) + + var pledgeInfoList []*PledgeInformation = make([]*PledgeInformation, 0) + pledgeTokensList := strings.Split(pledgeTokens, ",") + + if len(pledgeTokensList) == 0 { + return nil, fmt.Errorf("expected atleast one pledged token for unpledging") } - err = c.w.UnpledgeWholeToken(did, t, tokenType) + + for _, pledgeToken := range pledgeTokensList { + var tokenValue float64 + var tokenType int + + // Read Token from token hash + walletToken, err := c.w.ReadToken(pledgeToken) + if err != nil { + return nil, err + } + tokenValue = walletToken.TokenValue + + c.log.Debug(fmt.Sprintf("Tx: %v, Status of pledge token %v is %v", transactionID, pledgeToken, walletToken.TokenStatus)) + + if c.testNet { + if tokenValue == 1 { + tokenType = tkn.TestTokenType + } else if tokenValue < 1 { + tokenType = tkn.TestPartTokenType + } + } else { + if tokenValue == 1 { + tokenType = tkn.RBTTokenType + } else if tokenValue < 1 { + tokenType = tkn.PartTokenType + } + } + + b := c.w.GetLatestTokenBlock(pledgeToken, tokenType) + if b == nil { + c.log.Error("Failed to unpledge invalid tokne chain block for token ", pledgeToken, " having token type as ", tokenType) + return nil, fmt.Errorf("Failed to unpledge invalid tokne chain block for token ", pledgeToken, " having token type as ", tokenType) + } + + if b.GetTransType() != block.TokenPledgedType { + c.log.Error(fmt.Sprintf("failed while unpledging token %v, token must be in pledged state before unpledging", pledgeToken)) + return nil, fmt.Errorf("failed while unpledging token %v, token must be in pledged state before unpledging", pledgeToken) + } + + pledgeTokenBlockID, err := b.GetBlockID(pledgeToken) + if err != nil { + errMsg := fmt.Sprintf("failed while unpledging token %v, unable to fetch block ID", pledgeToken) + c.log.Error(errMsg) + return nil, errors.New(errMsg) + } + + ctcb := make(map[string]*block.Block) + tsb := make([]block.TransTokens, 0) + + ts := block.TransTokens{ + Token: pledgeToken, + TokenType: tokenType, + } + + dc, ok := c.qc[quorumDID] + if !ok { + c.log.Error("Failed to get quorum did crypto") + return nil, fmt.Errorf("failed to get quorum did crypto") + } + tsb = append(tsb, ts) + ctcb[pledgeToken] = b + currentTime := time.Now() + + tcb := block.TokenChainBlock{ + TransactionType: block.TokenUnpledgedType, + TokenOwner: quorumDID, + TransInfo: &block.TransInfo{ + Comment: "Token is un pledged at " + currentTime.String(), + Tokens: tsb, + }, + Epoch: int(currentTime.Unix()), + } + + nb := block.CreateNewBlock(ctcb, &tcb) + if nb == nil { + c.log.Error("Failed to create new token chain block") + return nil, fmt.Errorf("failed to create new token chain block") + } + + err = nb.UpdateSignature(dc) + if err != nil { + c.log.Error("Failed to update the signature", "err", err) + return nil, fmt.Errorf("failed to update the signature") + } + + err = c.w.CreateTokenBlock(nb) + if err != nil { + c.log.Error("Failed to update token chain block", "err", err) + return nil, err + } + + err = c.w.UnpledgeWholeToken(quorumDID, pledgeToken, tokenType) + if err != nil { + c.log.Error("Failed to update un pledge token", "err", err) + return nil, err + } + + unpledgeTokenBlockID, err := nb.GetBlockID(pledgeToken) + if err != nil { + errMsg := fmt.Sprintf("failed while unpledging token %v, unable to fetch block ID", pledgeToken) + c.log.Error(errMsg) + return nil, errors.New(errMsg) + } + + // Add pledge and unpledge block information of a Pledged token + pledgeInfoList = append(pledgeInfoList, &PledgeInformation{ + TokenID: pledgeToken, + TokenType: tokenType, + PledgeBlockID: pledgeTokenBlockID, + UnpledgeBlockID: unpledgeTokenBlockID, + QuorumDID: quorumDID, + TransactionID: transactionID, + }) + } + + // If the unpledging is happening after the pledging period, we can safely remove + // the TokenStateHash table records for the input transactionID + err := c.w.RemoveTokenStateHashByTransactionID(transactionID) if err != nil { - c.log.Error("Failed to update un pledge token", "err", err) - return err + return nil, err } - return nil + + return pledgeInfoList, nil } diff --git a/core/unpledge/Difficultlevel.go b/core/unpledge/Difficultlevel.go deleted file mode 100644 index 6b756d3f..00000000 --- a/core/unpledge/Difficultlevel.go +++ /dev/null @@ -1,10 +0,0 @@ -package unpledge - -var DiffLevel = map[int]int{ - 0: 0, - 1: 6, - 2: 6, - 3: 6, - 4: 6, - 5: 8, -} diff --git a/core/unpledge/unpledge.go b/core/unpledge/unpledge.go index 9b119ef0..9cdc4448 100644 --- a/core/unpledge/unpledge.go +++ b/core/unpledge/unpledge.go @@ -1,31 +1,16 @@ package unpledge import ( - "crypto/sha256" - "errors" - "fmt" - "math/rand" - "os" - "strconv" - "strings" - "sync" - "time" - - "github.com/rubixchain/rubixgoplatform/block" "github.com/rubixchain/rubixgoplatform/core/storage" "github.com/rubixchain/rubixgoplatform/core/wallet" - "github.com/rubixchain/rubixgoplatform/token" - "github.com/rubixchain/rubixgoplatform/wrapper/logger" - "golang.org/x/crypto/sha3" + //tkn "github.com/rubixchain/rubixgoplatform/token" + "github.com/rubixchain/rubixgoplatform/wrapper/logger" ) const ( - RecordInterval int = 5000 - Difficultlevel int = 6 -) + PledgePeriodInSeconds int = 7 * 24 * 60 * 60 -const ( UnpledgeQueueTable string = "unpledgequeue" ) @@ -33,324 +18,75 @@ type UnPledge struct { s storage.Storage testNet bool w *wallet.Wallet - l sync.Mutex - running bool - dir string cb UnpledgeCBType log logger.Logger } -type UnpledgeTokenList struct { - Token string `gorm:"column:token"` +type UnpledgeQueueInfo struct { + TransactionID string `gorm:"column:tx_id;primaryKey"` + PledgeTokens string `gorm:"column:pledge_tokens"` + Epoch int64 `gorm:"column:epoch"` + QuorumDID string `gorm:"column:quorum_did"` +} + +type UnpledgeCBType func(transactionID string, pledgeTokens string, quorumDID string) ([]*PledgeInformation, error) +type ReceiverOwnershipFunc func(transactionId string, receiverPeer string, receiverDID string, quorumDID string) (bool, error) + +type TransTokenBlock struct { + TokenID string `json:"token_id"` + TransferBlock string `json:"token_block"` +} + +type PledgeUnpledgeBlock struct { + TokenID string `json:"token_id"` + PledgeBlock string `json:"pledge_block"` + UnpledgeBlock string `json:"unpledge_block"` } -type UnpledgeCBType func(t string, file string) error +type PledgeInformation struct { + TokenID string `json:"token_id"` + TokenType int `json:"token_type"` + PledgeBlockID string `json:"pledge_block_id"` + UnpledgeBlockID string `json:"unpledge_block_id"` + QuorumDID string `json:"quorum_did"` + TransactionID string `json:"transaction_id"` +} -func InitUnPledge(s storage.Storage, w *wallet.Wallet, testNet bool, dir string, cb UnpledgeCBType, log logger.Logger) (*UnPledge, error) { +func InitUnPledge(s storage.Storage, w *wallet.Wallet, testNet bool, log logger.Logger) (*UnPledge, error) { up := &UnPledge{ s: s, testNet: testNet, w: w, - dir: dir, - cb: cb, log: log.Named("unpledge"), } - err := up.s.Init(UnpledgeQueueTable, UnpledgeTokenList{}, true) + err := up.s.Init(UnpledgeQueueTable, UnpledgeQueueInfo{}, true) if err != nil { up.log.Error("failed to init unpledge token list table", "err", err) return nil, err } - var list []UnpledgeTokenList - err = up.s.Read(UnpledgeQueueTable, &list, "token != ?", "") - if err != nil { - tks, err := up.w.GetAllPledgedTokens() - if err == nil { - list = make([]UnpledgeTokenList, 0) - for i := range tks { - l := UnpledgeTokenList{ - Token: tks[i].TokenID, - } - list = append(list, l) - } - for i := range list { - err = up.s.Write(UnpledgeQueueTable, &list[i]) - if err != nil { - up.log.Error("Failed to write unpledge list", "err", err) - return nil, err - } - } - } - } - //go up.runUnpledge() - return up, nil -} - -func (up *UnPledge) RunUnpledge() { - go up.runUnpledge() -} - -func sha2Hash256(input string) string { - hash := sha256.Sum256([]byte(input)) - hashedInput := fmt.Sprintf("%x", hash) - return hashedInput -} - -func sha3Hash256(input string) string { - hash := sha3.Sum256([]byte(input)) - hashedInput := fmt.Sprintf("%x", hash) - return hashedInput -} -func sha3Hash256Loop(input string) string { - var hashedInput string - for i := 0; i < RecordInterval; i++ { - hash := sha3.Sum256([]byte(input)) - hashedInput = fmt.Sprintf("%x", hash) - input = hashedInput - } - return hashedInput -} - -func (up *UnPledge) isRunning() bool { - up.l.Lock() - s := up.running - up.l.Unlock() - return s + return up, nil } -func (up *UnPledge) AddUnPledge(t string) { - var list UnpledgeTokenList - err := up.s.Read(UnpledgeQueueTable, &list, "token = ?", t) +func (up *UnPledge) AddUnPledge(txId string, pledgeTokens string, epoch int64, quorumDID string) error { + var unpledgeQueueInfo UnpledgeQueueInfo + err := up.s.Read(UnpledgeQueueTable, &unpledgeQueueInfo, "tx_id = ?", txId) if err == nil { - up.log.Error("Token already in the unpledge list") - return - } - list.Token = t - err = up.s.Write(UnpledgeQueueTable, &list) - if err != nil { - up.log.Error("Error adding token "+t+" to unpledge list", "err", err) - return + up.log.Error("Tokens are already in the unpledge list") + return err } - go up.runUnpledge() -} - -func (up *UnPledge) runUnpledge() { - up.l.Lock() - if up.running { - up.l.Unlock() - return - } - up.log.Info("Unpledging started") - up.running = true - up.l.Unlock() - defer func() { - up.l.Lock() - up.running = false - up.l.Unlock() - }() - for { - var list UnpledgeTokenList - err := up.s.Read(UnpledgeQueueTable, &list, "token != ?", "") - if err != nil { - up.log.Info("All tokens are unplegded") - break - } - st := time.Now() - t := list.Token - unpledgetokendetails, err := up.w.ReadToken(t) - if err != nil { - up.log.Error("Failed to fetch unpledge token details ", err) - up.s.Delete(UnpledgeQueueTable, &UnpledgeTokenList{}, "token=?", t) - continue - } - var tt int - if up.testNet { - if unpledgetokendetails.TokenValue == 1 { - tt = token.TestTokenType - } else if unpledgetokendetails.TokenValue < 1 { - tt = token.TestPartTokenType - } - } else { - if unpledgetokendetails.TokenValue == 1 { - tt = token.RBTTokenType - } else if unpledgetokendetails.TokenValue < 1 { - tt = token.PartTokenType - } - } - b := up.w.GetLatestTokenBlock(t, tt) - if b == nil { - up.log.Error("Failed to get the latest token block, removing the token from the unpledge list") - up.s.Delete(UnpledgeQueueTable, &UnpledgeTokenList{}, "token=?", t) - continue - } - bid, err := b.GetBlockID(t) - if err != nil { - up.log.Error("Failed to get the block id, removing the token from the unpledge list") - up.s.Delete(UnpledgeQueueTable, &UnpledgeTokenList{}, "token=?", t) - continue - } - if b.GetTransType() != block.TokenPledgedType { - up.log.Error("Token is not in pledged state, removing the token from the unpledge list") - up.s.Delete(UnpledgeQueueTable, &UnpledgeTokenList{}, "token=?", t) - continue - } - blk := b.GetTransBlock() - if blk == nil { - refID := b.GetRefID() - if refID == "" { - up.log.Error("Token block missing transaction block, removing the token from the unpledge list") - up.s.Delete(UnpledgeQueueTable, &UnpledgeTokenList{}, "token=?", t) - continue - } - ss := strings.Split(refID, ",") - if len(ss) != 3 { - up.log.Error("Invalid reference ID, removing the token from the unpledge list") - up.s.Delete(UnpledgeQueueTable, &UnpledgeTokenList{}, "token=?", t) - continue - } - tt, err := strconv.ParseInt(ss[1], 10, 32) - if err != nil { - up.log.Error("Invalid reference ID, removing the token from the unpledge list", "err", err) - up.s.Delete(UnpledgeQueueTable, &UnpledgeTokenList{}, "token=?", t) - continue - } - blk, err = up.w.GetTokenBlock(ss[0], int(tt), ss[2]) - if err != nil { - up.log.Error("Failed to get transaction block, removing the token from the unpledge list", "err", err) - up.s.Delete(UnpledgeQueueTable, &UnpledgeTokenList{}, "token=?", t) - continue - } - } - nb := block.InitBlock(blk, nil) - if nb == nil { - up.log.Error("Invalid transaction block, removing the token from the unpledge list") - up.s.Delete(UnpledgeQueueTable, &UnpledgeTokenList{}, "token=?", t) - continue - } - tid := nb.GetTid() - rdid := nb.GetReceiverDID() - - hash := sha2Hash256(t + rdid + bid) - fileName := up.dir + t + ".proof" - f, err := os.Create(fileName) - if err != nil { - up.log.Error("Failed to create file, removing the token from the unpledge list") - up.s.Delete(UnpledgeQueueTable, &UnpledgeTokenList{}, "token=?", t) - continue - } - - // ::TODO:: need to update - dl := Difficultlevel - targetHash := tid[len(tid)-dl:] - f.WriteString(fmt.Sprintf("%d\n", dl)) - f.WriteString(hash + "\n") - count := 1 - for { - hash = sha3Hash256(hash) - if targetHash == hash[len(hash)-dl:] { - f.WriteString(hash + "\n") - break - } - if count%RecordInterval == 0 { - f.WriteString(hash + "\n") - } - count++ - } - f.Close() - if up.cb == nil { - up.log.Error("Callback function not set, removing the token from the unpledge list") - up.s.Delete(UnpledgeQueueTable, &UnpledgeTokenList{}, "token=?", t) - continue - } - err = up.cb(t, fileName) - if err != nil { - up.log.Error("Error in unpledge alback, removing the token from the unpledge list", "err", err) - up.s.Delete(UnpledgeQueueTable, &UnpledgeTokenList{}, "token=?", t) - continue - } - et := time.Now() - df := et.Sub(st) - up.log.Info("Unpledging completed for the token " + t + " in " + df.String()) - up.s.Delete(UnpledgeQueueTable, &UnpledgeTokenList{}, "token=?", t) - } -} -func (up *UnPledge) ProofVerification(tokenID string, proof []string, rdid string, tid string, tokenType int) (bool, error) { + unpledgeQueueInfo.TransactionID = txId + unpledgeQueueInfo.PledgeTokens = pledgeTokens + unpledgeQueueInfo.Epoch = epoch + unpledgeQueueInfo.QuorumDID = quorumDID - blk := up.w.GetLatestTokenBlock(tokenID, tokenType) - - bid, err := blk.GetPrevBlockID(tokenID) + err = up.s.Write(UnpledgeQueueTable, &unpledgeQueueInfo) if err != nil { - up.log.Error("Failed to get the block id. Unable to verify proof file") - return false, err - } - - valueHashed := sha2Hash256(tokenID + rdid + bid) - if proof[0] == "" { - err := errors.New("First line of proof empty. Unable to verify proof file") - up.log.Error(err.Error()) - return false, err - } - dl := Difficultlevel - if proof[0] != strconv.Itoa(dl) { - err := errors.New("First line of proof mismatch. Unable to verify proof file") - up.log.Error(err.Error()) - return false, err - } - - if proof[1] != valueHashed { - err := errors.New("Second line of proof mismatch. Unable to verify proof file") - up.log.Error(err.Error()) - return false, err + up.log.Error("Error adding tx "+txId+" to unpledge list", "err", err) + return err } - proofToVerify := proof[1:] // Exculding firstline (Difficuilty level) - lenProof := len(proof) - lenProoftoVerify := len(proofToVerify) - l := lenProoftoVerify / 2 - - firstHalf := proof[1 : l-1] - secondHalf := proof[l : lenProoftoVerify-2] - - rand.Seed(time.Now().UnixNano()) - - randIndexInFH := rand.Intn(len(firstHalf) - 2) - randIndexInSH := rand.Intn(len(secondHalf) - 2) - - randomHashInFH := firstHalf[randIndexInFH] - randomHashInSH := secondHalf[randIndexInSH] - - targetHashInFH := firstHalf[randIndexInFH+1] - targetHashInSH := secondHalf[randIndexInSH+1] - - if sha3Hash256Loop(randomHashInFH) != targetHashInFH || sha3Hash256Loop(randomHashInSH) != targetHashInSH { - err := errors.New("Random hash verification fail. Unable to verify proof file") - up.log.Error(err.Error()) - return false, err - } - - var c int - counter := 0 - target := proof[lenProof-2] - lastHash := proof[lenProof-1] - suffixLasthash := lastHash[len(lastHash)-dl:] - - for { - targetHash := sha3Hash256(target) - suffixTarget := targetHash[len(targetHash)-dl:] - - if suffixTarget == suffixLasthash || counter > RecordInterval { - c = counter - break - } - counter++ - target = targetHash - } - if c > RecordInterval-1 || suffixLasthash != tid[len(tid)-dl:] { - up.log.Error("Last line of proof mismatch, Unable to verify proof file") - return false, err - } else { - up.log.Info("Proof Verified for " + tokenID) - return true, nil - } + return nil } + diff --git a/core/wallet/credit.go b/core/wallet/credit.go index 3ae3fb85..21589352 100644 --- a/core/wallet/credit.go +++ b/core/wallet/credit.go @@ -1,10 +1,13 @@ package wallet + type Credit struct { DID string `gorm:"column:did"` Credit string `gorm:"column:credit;size:4000"` + Tx string `gorm:"column:tx"` } + func (w *Wallet) StoreCredit(did string, credit string) error { c := &Credit{ DID: did, diff --git a/core/wallet/data_token.go b/core/wallet/data_token.go index d601dc5b..5be38c7b 100644 --- a/core/wallet/data_token.go +++ b/core/wallet/data_token.go @@ -2,18 +2,12 @@ package wallet import ( "fmt" -) -type DataToken struct { - TokenID string `gorm:"column:token_id;primaryKey" json:"token_id"` - DID string `gorm:"column:did" json:"did"` - CommitterDID string `gorm:"column:commiter_did" json:"comiter_did"` - BatchID string `gorm:"column:batch_id" json:"batch_id"` - TokenStatus int `gorm:"column:token_status;" json:"token_status"` -} + "github.com/rubixchain/rubixgoplatform/core/model" +) // CreateDataToken write data token into db -func (w *Wallet) CreateDataToken(dt *DataToken) error { +func (w *Wallet) CreateDataToken(dt *model.DataToken) error { err := w.s.Write(DataTokenStorage, dt) if err != nil { w.log.Error("Failed to write data token", "err", err) @@ -22,10 +16,10 @@ func (w *Wallet) CreateDataToken(dt *DataToken) error { return nil } -func (w *Wallet) GetAllDataTokens(did string) ([]DataToken, error) { +func (w *Wallet) GetAllDataTokens(did string) ([]model.DataToken, error) { w.dtl.Lock() defer w.dtl.Unlock() - var dts []DataToken + var dts []model.DataToken err := w.s.Read(DataTokenStorage, &dts, "did=?", did) if err != nil { return nil, err @@ -33,10 +27,10 @@ func (w *Wallet) GetAllDataTokens(did string) ([]DataToken, error) { return dts, nil } -func (w *Wallet) GetDataToken(batchID string) ([]DataToken, error) { +func (w *Wallet) GetDataToken(batchID string) ([]model.DataToken, error) { w.dtl.Lock() defer w.dtl.Unlock() - var dts []DataToken + var dts []model.DataToken err := w.s.Read(DataTokenStorage, &dts, "batch_id=? AND token_status=?", batchID, TokenIsFree) if err != nil { return nil, err @@ -54,10 +48,10 @@ func (w *Wallet) GetDataToken(batchID string) ([]DataToken, error) { return dts, nil } -func (w *Wallet) GetDataTokenByDID(did string) ([]DataToken, error) { +func (w *Wallet) GetDataTokenByDID(did string) ([]model.DataToken, error) { w.dtl.Lock() defer w.dtl.Unlock() - var dts []DataToken + var dts []model.DataToken err := w.s.Read(DataTokenStorage, &dts, "did=?", did) if err != nil { return nil, err @@ -68,7 +62,7 @@ func (w *Wallet) GetDataTokenByDID(did string) ([]DataToken, error) { return dts, nil } -func (w *Wallet) ReleaseDataToken(dts []DataToken) error { +func (w *Wallet) ReleaseDataToken(dts []model.DataToken) error { w.dtl.Lock() defer w.dtl.Unlock() for i := range dts { @@ -81,7 +75,7 @@ func (w *Wallet) ReleaseDataToken(dts []DataToken) error { return nil } -func (w *Wallet) CommitDataToken(dts []DataToken) error { +func (w *Wallet) CommitDataToken(dts []model.DataToken) error { w.dtl.Lock() defer w.dtl.Unlock() for i := range dts { diff --git a/core/wallet/token.go b/core/wallet/token.go index 7bfad11b..533693ed 100644 --- a/core/wallet/token.go +++ b/core/wallet/token.go @@ -3,6 +3,7 @@ package wallet import ( "fmt" "os" + "strings" "github.com/rubixchain/rubixgoplatform/block" "github.com/rubixchain/rubixgoplatform/contract" @@ -37,11 +38,13 @@ const ( ) type Token struct { - TokenID string `gorm:"column:token_id;primaryKey"` - ParentTokenID string `gorm:"column:parent_token_id"` - TokenValue float64 `gorm:"column:token_value"` - DID string `gorm:"column:did"` - TokenStatus int `gorm:"column:token_status;"` + TokenID string `gorm:"column:token_id;primaryKey"` + ParentTokenID string `gorm:"column:parent_token_id"` + TokenValue float64 `gorm:"column:token_value"` + DID string `gorm:"column:did"` + TokenStatus int `gorm:"column:token_status;"` + TokenStateHash string `gorm:"column:token_state_hash"` + TransactionID string `gorm:"column:transaction_id"` } func (w *Wallet) CreateToken(t *Token) error { @@ -111,6 +114,19 @@ func (w *Wallet) GetAllTokens(did string) ([]Token, error) { return t, nil } +func (w *Wallet) GetFreeTokens(did string) ([]Token, error) { + var t []Token + err := w.s.Read(TokenStorage, &t, "token_status=? AND did=?", TokenIsFree, did) + if err != nil { + if strings.Contains(err.Error(), "no records found") { + return []Token{}, nil + } else { + return nil, err + } + } + return t, nil +} + func (w *Wallet) GetAllPledgedTokens() ([]Token, error) { var t []Token err := w.s.Read(TokenStorage, &t, "token_status=?", TokenIsPledged) @@ -344,6 +360,8 @@ func (w *Wallet) TokensTransferred(did string, ti []contract.TokenInfo, b *block return err } t.TokenStatus = TokenIsTransferred + t.TransactionID = b.GetTid() + err = w.s.Update(TokenStorage, &t, "did=? AND token_id=?", did, ti[i].Token) if err != nil { return err @@ -415,9 +433,10 @@ func (w *Wallet) TokensReceived(did string, ti []contract.TokenInfo, b *block.Bl return err } } - t.DID = did t.TokenStatus = TokenIsFree + t.TransactionID = b.GetTid() + err = w.s.Update(TokenStorage, &t, "token_id=?", ti[i].Token) if err != nil { return err @@ -453,6 +472,20 @@ func (w *Wallet) TokensReceived(did string, ti []contract.TokenInfo, b *block.Bl return nil } +func (w *Wallet) TokenStateHashUpdate(tokenwithtokenhash []string) { + w.l.Lock() + defer w.l.Unlock() + var t Token + for _, val := range tokenwithtokenhash { + token := strings.Split(val, ".")[0] + tokenstatehash := strings.Split(val, ".")[1] + _ = w.s.Read(TokenStorage, &t, "token_id=?", token) + t.TokenStateHash = tokenstatehash + _ = w.s.Update(TokenStorage, &t, "token_id=?", token) + } + +} + func (w *Wallet) CommitTokens(did string, rbtTokens []string) error { w.l.Lock() defer w.l.Unlock() @@ -593,3 +626,100 @@ func (w *Wallet) UnlockLockedTokens(did string, tokenList []string) error { } return nil } + +func (w *Wallet) AddTokenStateHash(did string, tokenStateHashes []string, pledgedtokens []string, TransactionID string) error { + w.l.Lock() + defer w.l.Unlock() + var td TokenStateDetails + if tokenStateHashes == nil { + return nil + } + concatenatedpledgedtokens := strings.Join(pledgedtokens, ",") + + for _, tokenStateHash := range tokenStateHashes { + td.DID = did + td.PledgedTokens = concatenatedpledgedtokens + td.TokenStateHash = tokenStateHash + td.TransactionID = TransactionID + + err := w.s.Write(TokenStateHash, &td) + if err != nil { + w.log.Error("Token State Hash could not be added", "token state hash", tokenStateHash, "err", err) + return err + } + } + + return nil +} + +func (w *Wallet) GetTokenStateHashByTransactionID(transactionID string) ([]TokenStateDetails, error) { + var td []TokenStateDetails + err := w.s.Read(TokenStateHash, &td, "transaction_id = ?", transactionID) + if err != nil { + if strings.Contains(err.Error(), "no records found") { + return []TokenStateDetails{}, nil + } else { + w.log.Error("Failed to get token states", "err", err) + return nil, err + } + } + return td, nil +} + +func (w *Wallet) GetAllTokenStateHash() ([]TokenStateDetails, error) { + var td []TokenStateDetails + err := w.s.Read(TokenStateHash, &td, "did!=?", "") + if err != nil { + w.log.Error("Failed to get token states", "err", err) + return nil, err + } + return td, nil +} + +func (w *Wallet) RemoveTokenStateHash(tokenstatehash string) error { + var td TokenStateDetails + + //Getting all the details about a particular token state hash + err := w.s.Read(TokenStateHash, &td, "token_state_hash=?", tokenstatehash) + if err != nil { + if strings.Contains(err.Error(), "no records found") { + return nil + } else { + w.log.Error("Failed to fetch token state from DB", "err", err) + return err + } + } + + err = w.s.Delete(TokenStateHash, &td, "token_state_hash=?", tokenstatehash) + if err != nil { + w.log.Error("Failed to delete token state hash details from DB", "err", err) + return err + } + + return nil +} + +func (w *Wallet) RemoveTokenStateHashByTransactionID(transactionID string) error { + var td []TokenStateDetails + + //Getting all the details about a particular token state hash + err := w.s.Read(TokenStateHash, &td, "transaction_id=?", transactionID) + if err != nil { + if !strings.Contains(err.Error(), "no records found") { + w.log.Error("Failed to fetch token state from DB", "err", err) + return err + } else { + return nil + } + } + + if len(td) > 0 { + err = w.s.Delete(TokenStateHash, &td, "transaction_id=?", transactionID) + if err != nil { + w.log.Error("Failed to delete token state hash details from DB", "err", err) + return err + } + } + + return nil +} diff --git a/core/wallet/token_chain.go b/core/wallet/token_chain.go index 5d3060d8..84ec1c43 100644 --- a/core/wallet/token_chain.go +++ b/core/wallet/token_chain.go @@ -34,6 +34,13 @@ const ( const TCBlockCountLimit int = 100 +type TokenStateDetails struct { + DID string `gorm:"column:did" json:"did"` + TokenStateHash string `gorm:"column:token_state_hash;primaryKey" json:"token_state_hash"` + PledgedTokens string `gorm:"column:pledged_token" json:"pledged_token"` + TransactionID string `gorm:"column:transaction_id" json:"transaction_id"` +} + func tcsType(tokenType int) string { tt := "wt" switch tokenType { diff --git a/core/wallet/transaction_history.go b/core/wallet/transaction_history.go index ef666b33..2ed5791b 100644 --- a/core/wallet/transaction_history.go +++ b/core/wallet/transaction_history.go @@ -2,6 +2,8 @@ package wallet import ( "time" + + "github.com/rubixchain/rubixgoplatform/core/model" ) const ( @@ -11,28 +13,9 @@ const ( ExecuteMode ) -type TransactionDetails struct { - TransactionID string `gorm:"column:transaction_id;primaryKey"` - TransactionType string `gorm:"column:transaction_type"` - BlockID string `gorm:"column:block_id"` - Mode int `gorm:"column:mode"` - SenderDID string `gorm:"column:sender_did"` - ReceiverDID string `gorm:"column:receiver_did"` - Amount float64 `gorm:"column:amount"` - TotalTime float64 `gorm:"column:total_time"` - Comment string `gorm:"column:comment"` - DateTime time.Time `gorm:"column:date_time"` - Status bool `gorm:"column:status"` - DeployerDID string `gorm:"column:deployer_did"` -} -type TransactionCount struct { - DID string - TxnSend int - TxnReceived int -} -func (w *Wallet) AddTransactionHistory(td *TransactionDetails) error { +func (w *Wallet) AddTransactionHistory(td *model.TransactionDetails) error { err := w.s.Write(TransactionStorage, td) if err != nil { w.log.Error("Failed to store transaction history", "err", err) @@ -41,8 +24,8 @@ func (w *Wallet) AddTransactionHistory(td *TransactionDetails) error { return nil } -func (w *Wallet) GetTransactionDetailsbyTransactionId(transactionId string) (TransactionDetails, error) { - var th TransactionDetails +func (w *Wallet) GetTransactionDetailsbyTransactionId(transactionId string) (model.TransactionDetails, error) { + var th model.TransactionDetails //var tt []w.TokensTransferred //var ql []w.QuorumList err := w.s.Read(TransactionStorage, &th, "transaction_id=?", transactionId) @@ -53,8 +36,8 @@ func (w *Wallet) GetTransactionDetailsbyTransactionId(transactionId string) (Tra return th, nil } -func (w *Wallet) GetTransactionByComment(comment string) ([]TransactionDetails, error) { - var td []TransactionDetails +func (w *Wallet) GetTransactionByComment(comment string) ([]model.TransactionDetails, error) { + var td []model.TransactionDetails err := w.s.Read(TransactionStorage, &td, "comment=?", comment) if err != nil { @@ -64,8 +47,8 @@ func (w *Wallet) GetTransactionByComment(comment string) ([]TransactionDetails, return td, err } -func (w *Wallet) GetTransactionByReceiver(receiver string) ([]TransactionDetails, error) { - var td []TransactionDetails +func (w *Wallet) GetTransactionByReceiver(receiver string) ([]model.TransactionDetails, error) { + var td []model.TransactionDetails err := w.s.Read(TransactionStorage, &td, "receiver_did=?", receiver) if err != nil { @@ -75,8 +58,8 @@ func (w *Wallet) GetTransactionByReceiver(receiver string) ([]TransactionDetails return td, nil } -func (w *Wallet) GetTransactionBySender(sender string) ([]TransactionDetails, error) { - var td []TransactionDetails +func (w *Wallet) GetTransactionBySender(sender string) ([]model.TransactionDetails, error) { + var td []model.TransactionDetails err := w.s.Read(TransactionStorage, &td, "sender_did=?", sender) if err != nil { @@ -86,8 +69,8 @@ func (w *Wallet) GetTransactionBySender(sender string) ([]TransactionDetails, er return td, nil } -func (w *Wallet) GetTransactionByDID(did string) ([]TransactionDetails, error) { - var td []TransactionDetails +func (w *Wallet) GetTransactionByDID(did string) ([]model.TransactionDetails, error) { + var td []model.TransactionDetails err := w.s.Read(TransactionStorage, &td, "sender_did=? OR receiver_did=?", did, did) if err != nil { @@ -97,8 +80,8 @@ func (w *Wallet) GetTransactionByDID(did string) ([]TransactionDetails, error) { return td, nil } -func (w *Wallet) GetTransactionByDIDAndDateRange(did string, startDate time.Time, endDate time.Time) ([]TransactionDetails, error) { - var td []TransactionDetails +func (w *Wallet) GetTransactionByDIDAndDateRange(did string, startDate time.Time, endDate time.Time) ([]model.TransactionDetails, error) { + var td []model.TransactionDetails err := w.s.Read(TransactionStorage, &td, "date_time >= ? AND date_time <= ? AND sender_did=? OR receiver_did=?", startDate, endDate, did, did) if err != nil { w.log.Error("Failed to get transaction details with did and date range", did, startDate, endDate, "err", err) diff --git a/core/wallet/wallet.go b/core/wallet/wallet.go index f0a0666b..f1db89e1 100644 --- a/core/wallet/wallet.go +++ b/core/wallet/wallet.go @@ -5,6 +5,7 @@ import ( "sync" ipfsnode "github.com/ipfs/go-ipfs-api" + "github.com/rubixchain/rubixgoplatform/core/model" "github.com/rubixchain/rubixgoplatform/core/storage" "github.com/rubixchain/rubixgoplatform/wrapper/logger" "github.com/syndtr/goleveldb/leveldb" @@ -27,6 +28,7 @@ const ( SmartContractTokenChainStorage string = "smartcontractokenchainstorage" SmartContractStorage string = "smartcontract" CallBackUrlStorage string = "callbackurl" + TokenStateHash string = "TokenStateHashTable" ) type WalletConfig struct { @@ -100,7 +102,7 @@ func InitWallet(s storage.Storage, dir string, log logger.Logger) (*Wallet, erro w.log.Error("Failed to initialize whole token storage", "err", err) return nil, err } - err = w.s.Init(DataTokenStorage, &DataToken{}, true) + err = w.s.Init(DataTokenStorage, &model.DataToken{}, true) if err != nil { w.log.Error("Failed to initialize data token storage", "err", err) return nil, err @@ -120,7 +122,7 @@ func InitWallet(s storage.Storage, dir string, log logger.Logger) (*Wallet, erro w.log.Error("Failed to initialize DID Peer storage", "err", err) return nil, err } - err = w.s.Init(TransactionStorage, &TransactionDetails{}, true) + err = w.s.Init(TransactionStorage, &model.TransactionDetails{}, true) if err != nil { w.log.Error("Failed to initialize Transaction storage", "err", err) return nil, err @@ -149,6 +151,12 @@ func InitWallet(s storage.Storage, dir string, log logger.Logger) (*Wallet, erro return nil, err } + err = w.s.Init(TokenStateHash, &TokenStateDetails{}, true) + if err != nil { + w.log.Error("Failed to initialize TokenStateHash", "err", err) + return nil, err + } + return w, nil } diff --git a/docs/docs.go b/docs/docs.go index 973f307b..5f24031b 100644 --- a/docs/docs.go +++ b/docs/docs.go @@ -86,6 +86,38 @@ const docTemplate = `{ } } }, + "/api/check-pinned-state": { + "delete": { + "description": "This API is used to check if the token state for which the token is pledged is exhausted or not.", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "Account" + ], + "summary": "Check for exhausted token state hash", + "parameters": [ + { + "type": "string", + "description": "Token State Hash", + "name": "tokenstatehash", + "in": "query", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/model.BasicResponse" + } + } + } + } + }, "/api/commit-data-token": { "post": { "description": "This API will create data token", @@ -590,6 +622,26 @@ const docTemplate = `{ } } }, + "/api/get-pledgedtoken-details": { + "get": { + "description": "This API allows the user to get details about the tokens the quorums have pledged i.e. which token is pledged for which token state", + "produces": [ + "application/json" + ], + "tags": [ + "Account" + ], + "summary": "Get details about the pledged tokens", + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/model.TokenStateResponse" + } + } + } + } + }, "/api/get-smart-contract-token-chain-data": { "post": { "description": "This API will return smart contract token chain data", @@ -683,6 +735,41 @@ const docTemplate = `{ } } }, + "/api/initiate-self-transfer": { + "post": { + "description": "This API will initiate self RBT transfer for a specific DID", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "Account" + ], + "summary": "Initiate Self Transfer", + "operationId": "initiate-self-transfer", + "parameters": [ + { + "description": "Intitate RBT transfer", + "name": "input", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/server.RBTTransferRequestSwaggoInput" + } + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/model.BasicResponse" + } + } + } + } + }, "/api/register-callback-url": { "post": { "description": "This API will register call back url for when updated come for smart contract token", @@ -718,6 +805,30 @@ const docTemplate = `{ } } }, + "/api/run-unpledge": { + "post": { + "description": "This API will initiate self RBT transfer for a specific DID", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "Account" + ], + "summary": "Run Unpledge", + "operationId": "run-unpledge", + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/model.BasicResponse" + } + } + } + } + }, "/api/signature-response": { "post": { "description": "This API is used to supply the password for the node along with the ID generated when Initiate RBT transfer is called.", @@ -881,6 +992,52 @@ const docTemplate = `{ } } }, + "model.PledgedTokenStateDetails": { + "type": "object", + "properties": { + "did": { + "type": "string" + }, + "token": { + "type": "string" + }, + "token_state": { + "type": "string" + } + } + }, + "model.TokenStateResponse": { + "type": "object", + "properties": { + "message": { + "type": "string" + }, + "result": {}, + "status": { + "type": "boolean" + }, + "token_state_details": { + "type": "array", + "items": { + "$ref": "#/definitions/model.PledgedTokenStateDetails" + } + } + } + }, + "model.TransactionCount": { + "type": "object", + "properties": { + "did": { + "type": "string" + }, + "txnReceived": { + "type": "integer" + }, + "txnSend": { + "type": "integer" + } + } + }, "model.TxnCountForDID": { "type": "object", "properties": { @@ -894,7 +1051,7 @@ const docTemplate = `{ "txnCount": { "type": "array", "items": { - "$ref": "#/definitions/wallet.TransactionCount" + "$ref": "#/definitions/model.TransactionCount" } } } @@ -1024,20 +1181,6 @@ const docTemplate = `{ "type": "string" } } - }, - "wallet.TransactionCount": { - "type": "object", - "properties": { - "did": { - "type": "string" - }, - "txnReceived": { - "type": "integer" - }, - "txnSend": { - "type": "integer" - } - } } }, "securityDefinitions": { diff --git a/docs/swagger.json b/docs/swagger.json index 95143433..341104de 100644 --- a/docs/swagger.json +++ b/docs/swagger.json @@ -78,6 +78,38 @@ } } }, + "/api/check-pinned-state": { + "delete": { + "description": "This API is used to check if the token state for which the token is pledged is exhausted or not.", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "Account" + ], + "summary": "Check for exhausted token state hash", + "parameters": [ + { + "type": "string", + "description": "Token State Hash", + "name": "tokenstatehash", + "in": "query", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/model.BasicResponse" + } + } + } + } + }, "/api/commit-data-token": { "post": { "description": "This API will create data token", @@ -582,6 +614,26 @@ } } }, + "/api/get-pledgedtoken-details": { + "get": { + "description": "This API allows the user to get details about the tokens the quorums have pledged i.e. which token is pledged for which token state", + "produces": [ + "application/json" + ], + "tags": [ + "Account" + ], + "summary": "Get details about the pledged tokens", + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/model.TokenStateResponse" + } + } + } + } + }, "/api/get-smart-contract-token-chain-data": { "post": { "description": "This API will return smart contract token chain data", @@ -675,6 +727,41 @@ } } }, + "/api/initiate-self-transfer": { + "post": { + "description": "This API will initiate self RBT transfer for a specific DID", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "Account" + ], + "summary": "Initiate Self Transfer", + "operationId": "initiate-self-transfer", + "parameters": [ + { + "description": "Intitate RBT transfer", + "name": "input", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/server.RBTTransferRequestSwaggoInput" + } + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/model.BasicResponse" + } + } + } + } + }, "/api/register-callback-url": { "post": { "description": "This API will register call back url for when updated come for smart contract token", @@ -710,6 +797,30 @@ } } }, + "/api/run-unpledge": { + "post": { + "description": "This API will initiate self RBT transfer for a specific DID", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "Account" + ], + "summary": "Run Unpledge", + "operationId": "run-unpledge", + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/model.BasicResponse" + } + } + } + } + }, "/api/signature-response": { "post": { "description": "This API is used to supply the password for the node along with the ID generated when Initiate RBT transfer is called.", @@ -873,6 +984,52 @@ } } }, + "model.PledgedTokenStateDetails": { + "type": "object", + "properties": { + "did": { + "type": "string" + }, + "token": { + "type": "string" + }, + "token_state": { + "type": "string" + } + } + }, + "model.TokenStateResponse": { + "type": "object", + "properties": { + "message": { + "type": "string" + }, + "result": {}, + "status": { + "type": "boolean" + }, + "token_state_details": { + "type": "array", + "items": { + "$ref": "#/definitions/model.PledgedTokenStateDetails" + } + } + } + }, + "model.TransactionCount": { + "type": "object", + "properties": { + "did": { + "type": "string" + }, + "txnReceived": { + "type": "integer" + }, + "txnSend": { + "type": "integer" + } + } + }, "model.TxnCountForDID": { "type": "object", "properties": { @@ -886,7 +1043,7 @@ "txnCount": { "type": "array", "items": { - "$ref": "#/definitions/wallet.TransactionCount" + "$ref": "#/definitions/model.TransactionCount" } } } @@ -1016,20 +1173,6 @@ "type": "string" } } - }, - "wallet.TransactionCount": { - "type": "object", - "properties": { - "did": { - "type": "string" - }, - "txnReceived": { - "type": "integer" - }, - "txnSend": { - "type": "integer" - } - } } }, "securityDefinitions": { diff --git a/docs/swagger.yaml b/docs/swagger.yaml index 17ba1455..82e29b4a 100644 --- a/docs/swagger.yaml +++ b/docs/swagger.yaml @@ -44,6 +44,36 @@ definitions: $ref: '#/definitions/model.NFTStatus' type: array type: object + model.PledgedTokenStateDetails: + properties: + did: + type: string + token: + type: string + token_state: + type: string + type: object + model.TokenStateResponse: + properties: + message: + type: string + result: {} + status: + type: boolean + token_state_details: + items: + $ref: '#/definitions/model.PledgedTokenStateDetails' + type: array + type: object + model.TransactionCount: + properties: + did: + type: string + txnReceived: + type: integer + txnSend: + type: integer + type: object model.TxnCountForDID: properties: message: @@ -53,7 +83,7 @@ definitions: type: boolean txnCount: items: - $ref: '#/definitions/wallet.TransactionCount' + $ref: '#/definitions/model.TransactionCount' type: array type: object server.DIDPeerMapTemp: @@ -137,15 +167,6 @@ definitions: password: type: string type: object - wallet.TransactionCount: - properties: - did: - type: string - txnReceived: - type: integer - txnSend: - type: integer - type: object info: contact: email: murali.c@ensurity.com @@ -198,6 +219,28 @@ paths: summary: Add NFTs tags: - NFT + /api/check-pinned-state: + delete: + consumes: + - application/json + description: This API is used to check if the token state for which the token + is pledged is exhausted or not. + parameters: + - description: Token State Hash + in: query + name: tokenstatehash + required: true + type: string + produces: + - application/json + responses: + "200": + description: OK + schema: + $ref: '#/definitions/model.BasicResponse' + summary: Check for exhausted token state hash + tags: + - Account /api/commit-data-token: post: consumes: @@ -531,6 +574,20 @@ paths: summary: Get Data Token tags: - Data Tokens + /api/get-pledgedtoken-details: + get: + description: This API allows the user to get details about the tokens the quorums + have pledged i.e. which token is pledged for which token state + produces: + - application/json + responses: + "200": + description: OK + schema: + $ref: '#/definitions/model.TokenStateResponse' + summary: Get details about the pledged tokens + tags: + - Account /api/get-smart-contract-token-chain-data: post: consumes: @@ -592,6 +649,29 @@ paths: summary: Initiate RBT Transfer tags: - Account + /api/initiate-self-transfer: + post: + consumes: + - application/json + description: This API will initiate self RBT transfer for a specific DID + operationId: initiate-self-transfer + parameters: + - description: Intitate RBT transfer + in: body + name: input + required: true + schema: + $ref: '#/definitions/server.RBTTransferRequestSwaggoInput' + produces: + - application/json + responses: + "200": + description: OK + schema: + $ref: '#/definitions/model.BasicResponse' + summary: Initiate Self Transfer + tags: + - Account /api/register-callback-url: post: consumes: @@ -616,6 +696,22 @@ paths: summary: Get Smart Contract Token Chain Data tags: - Smart Contract + /api/run-unpledge: + post: + consumes: + - application/json + description: This API will initiate self RBT transfer for a specific DID + operationId: run-unpledge + produces: + - application/json + responses: + "200": + description: OK + schema: + $ref: '#/definitions/model.BasicResponse' + summary: Run Unpledge + tags: + - Account /api/signature-response: post: consumes: diff --git a/grpcserver/token.go b/grpcserver/token.go index 28eb8fdd..a32526f9 100644 --- a/grpcserver/token.go +++ b/grpcserver/token.go @@ -87,7 +87,7 @@ func (rn *RubixNative) GetAllTokens(ctx context.Context, in *protos.TokenReq) (* resp := &protos.TokenResp{ TokenDetials: make([]*protos.TokenDetial, 0), } - for _, td := range tr.TokenDetials { + for _, td := range tr.TokenDetails { t := &protos.TokenDetial{ Token: td.Token, TokenState: int32(td.Status), diff --git a/server/self_transfer.go b/server/self_transfer.go new file mode 100644 index 00000000..3b9effd2 --- /dev/null +++ b/server/self_transfer.go @@ -0,0 +1,39 @@ +package server + +import ( + "github.com/rubixchain/rubixgoplatform/wrapper/ensweb" + "github.com/rubixchain/rubixgoplatform/core/model" +) + +// @Summary Initiate Self Transfer +// @Description This API will initiate self RBT transfer for a specific DID +// @Tags Account +// @ID initiate-self-transfer +// @Accept json +// @Produce json +// @Param input body RBTTransferRequestSwaggoInput true "Intitate RBT transfer" +// @Success 200 {object} model.BasicResponse +// @Router /api/initiate-self-transfer [post] +func (s *Server) SelfTransferHandle(req *ensweb.Request) *ensweb.Result { + var selfTransferReq model.RBTTransferRequest + err := s.ParseJSON(req, &selfTransferReq) + if err != nil { + return s.BasicResponse(req, false, "Invalid input", nil) + } + + senderDID := selfTransferReq.Sender + receiverDID := selfTransferReq.Receiver + + if receiverDID != "" && senderDID != receiverDID { + return s.BasicResponse(req, false, "Sender and Receiver must be same in case of self transfer", nil) + } + + if !s.validateDIDAccess(req, senderDID) { + return s.BasicResponse(req, false, "DID does not have an access", nil) + } + + s.c.AddWebReq(req) + + go s.c.InitiateRBTTransfer(req.ID, &selfTransferReq) + return s.didResponse(req, req.ID) +} \ No newline at end of file diff --git a/server/server.go b/server/server.go index bc0b7dd4..e4e7da59 100644 --- a/server/server.go +++ b/server/server.go @@ -161,6 +161,10 @@ func (s *Server) RegisterRoutes() { s.AddRoute(setup.APIAddExplorer, "POST", s.AuthHandle(s.APIAddExplorer, false, s.AuthError, true)) s.AddRoute(setup.APIRemoveExplorer, "POST", s.AuthHandle(s.APIRemoveExplorer, false, s.AuthError, true)) s.AddRoute(setup.APIAddPeerDetails, "POST", s.AuthHandle(s.APIAddPeerDetails, false, s.AuthError, true)) + s.AddRoute(setup.APIGetPledgedTokenDetails, "GET", s.AuthHandle(s.APIGetPledgedTokenDetails, false, s.AuthError, true)) + s.AddRoute(setup.APICheckPinnedState, "DELETE", s.AuthHandle(s.APICheckPinnedState, false, s.AuthError, true)) + s.AddRoute(setup.APISelfTransfer, "POST", s.AuthHandle(s.SelfTransferHandle, false, s.AuthError, true)) + s.AddRoute(setup.APIRunUnpledge, "POST", s.AuthHandle(s.RunUnpledgeHandle, false, s.AuthError, true)) } func (s *Server) ExitFunc() error { diff --git a/server/tokens.go b/server/tokens.go index 5db737c4..8c278152 100644 --- a/server/tokens.go +++ b/server/tokens.go @@ -1,6 +1,7 @@ package server import ( + "fmt" "net/http" "github.com/rubixchain/rubixgoplatform/core/model" @@ -130,3 +131,60 @@ func (s *Server) APISignatureResponse(req *ensweb.Request) *ensweb.Result { dc.InChan <- resp return s.didResponse(req, resp.ID) } + +// APIGetPledgedTokenDetails godoc +// @Summary Get details about the pledged tokens +// @Description This API allows the user to get details about the tokens the quorums have pledged i.e. which token is pledged for which token state +// @Tags Account +// @Produce json +// @Success 200 {object} model.TokenStateResponse +// @Router /api/get-pledgedtoken-details [get] +func (s *Server) APIGetPledgedTokenDetails(req *ensweb.Request) *ensweb.Result { + pledgedTokenInfo, err := s.c.GetPledgedInfo() + if err != nil { + return s.BasicResponse(req, false, err.Error(), nil) + } + tokenstateresponse := model.TokenStateResponse{ + BasicResponse: model.BasicResponse{ + Status: true, + Message: "Got pledged tokens with token states info successfully", + }, + PledgedTokenStateDetails: make([]model.PledgedTokenStateDetails, 0), + } + tokenstateresponse.PledgedTokenStateDetails = append(tokenstateresponse.PledgedTokenStateDetails, pledgedTokenInfo...) + return s.RenderJSON(req, tokenstateresponse, http.StatusOK) +} + +// APICheckPinnedState godoc +// @Summary Check for exhausted token state hash +// @Description This API is used to check if the token state for which the token is pledged is exhausted or not. +// @Tags Account +// @Accept json +// @Produce json +// @Param tokenstatehash query string true "Token State Hash" +// @Success 200 {object} model.BasicResponse +// @Router /api/check-pinned-state [delete] +func (s *Server) APICheckPinnedState(req *ensweb.Request) *ensweb.Result { + tokenstatehash := s.GetQuerry(req, "tokenstatehash") + + provList, err := s.c.GetDHTddrs(tokenstatehash) + if err != nil { + return s.BasicResponse(req, false, err.Error(), nil) + } + var br model.BasicResponse + if len(provList) == 0 { + br.Status = false + br.Message = fmt.Sprintf("No pins available on %s", tokenstatehash) + return s.RenderJSON(req, br, http.StatusOK) + } else { + br.Status = true + br.Result = provList + } + + err = s.c.UpdatePledgedTokenInfo(tokenstatehash) + if err != nil { + return s.BasicResponse(req, false, err.Error(), nil) + } + br.Message = "Got Pins on " + tokenstatehash + ". Updated the pledging detail in table and removed from pledged token state table." + return s.RenderJSON(req, br, http.StatusOK) +} diff --git a/server/txndetails.go b/server/txndetails.go index c4397c90..d261ed67 100644 --- a/server/txndetails.go +++ b/server/txndetails.go @@ -4,7 +4,6 @@ import ( "net/http" "github.com/rubixchain/rubixgoplatform/core/model" - "github.com/rubixchain/rubixgoplatform/core/wallet" "github.com/rubixchain/rubixgoplatform/setup" "github.com/rubixchain/rubixgoplatform/wrapper/ensweb" ) @@ -29,7 +28,7 @@ func (s *Server) APIGetTxnByTxnID(req *ensweb.Request) *ensweb.Result { Status: true, Message: "no records present for this Transaction ID : " + txnID, }, - TxnDetails: make([]wallet.TransactionDetails, 0), + TxnDetails: make([]model.TransactionDetails, 0), } return s.RenderJSON(req, &td, http.StatusOK) } @@ -39,7 +38,7 @@ func (s *Server) APIGetTxnByTxnID(req *ensweb.Request) *ensweb.Result { Status: false, Message: err.Error(), }, - TxnDetails: make([]wallet.TransactionDetails, 0), + TxnDetails: make([]model.TransactionDetails, 0), } return s.RenderJSON(req, &td, http.StatusOK) } @@ -48,7 +47,7 @@ func (s *Server) APIGetTxnByTxnID(req *ensweb.Request) *ensweb.Result { Status: true, Message: "Retrieved Txn Details", }, - TxnDetails: make([]wallet.TransactionDetails, 0), + TxnDetails: make([]model.TransactionDetails, 0), } td.TxnDetails = append(td.TxnDetails, res) @@ -80,7 +79,7 @@ func (s *Server) APIGetTxnByDID(req *ensweb.Request) *ensweb.Result { Message: "Either use Date range or Role for filter", Result: "", }, - TxnDetails: make([]wallet.TransactionDetails, 0), + TxnDetails: make([]model.TransactionDetails, 0), } return s.RenderJSON(req, &td, http.StatusOK) } @@ -95,7 +94,7 @@ func (s *Server) APIGetTxnByDID(req *ensweb.Request) *ensweb.Result { Message: "no records present for this DID : " + did, Result: "No data found", }, - TxnDetails: make([]wallet.TransactionDetails, 0), + TxnDetails: make([]model.TransactionDetails, 0), } return s.RenderJSON(req, &td, http.StatusOK) } @@ -106,7 +105,7 @@ func (s *Server) APIGetTxnByDID(req *ensweb.Request) *ensweb.Result { Message: err.Error(), Result: "No data found", }, - TxnDetails: make([]wallet.TransactionDetails, 0), + TxnDetails: make([]model.TransactionDetails, 0), } return s.RenderJSON(req, &td, http.StatusOK) } @@ -116,7 +115,7 @@ func (s *Server) APIGetTxnByDID(req *ensweb.Request) *ensweb.Result { Message: "Retrieved Txn Details", Result: "Successful", }, - TxnDetails: make([]wallet.TransactionDetails, 0), + TxnDetails: make([]model.TransactionDetails, 0), } td.TxnDetails = append(td.TxnDetails, res...) @@ -144,7 +143,7 @@ func (s *Server) APIGetTxnByComment(req *ensweb.Request) *ensweb.Result { Status: true, Message: "no records present for the comment : " + comment, }, - TxnDetails: make([]wallet.TransactionDetails, 0), + TxnDetails: make([]model.TransactionDetails, 0), } return s.RenderJSON(req, &td, http.StatusOK) } @@ -154,7 +153,7 @@ func (s *Server) APIGetTxnByComment(req *ensweb.Request) *ensweb.Result { Status: false, Message: err.Error(), }, - TxnDetails: make([]wallet.TransactionDetails, 0), + TxnDetails: make([]model.TransactionDetails, 0), } return s.RenderJSON(req, &td, http.StatusOK) } @@ -163,7 +162,7 @@ func (s *Server) APIGetTxnByComment(req *ensweb.Request) *ensweb.Result { Status: true, Message: "Retrieved Txn Details", }, - TxnDetails: make([]wallet.TransactionDetails, 0), + TxnDetails: make([]model.TransactionDetails, 0), } for i := range res { diff --git a/server/unpledge.go b/server/unpledge.go new file mode 100644 index 00000000..3fac238e --- /dev/null +++ b/server/unpledge.go @@ -0,0 +1,35 @@ +package server + +import ( + "fmt" + "net/http" + + "github.com/rubixchain/rubixgoplatform/core/model" + "github.com/rubixchain/rubixgoplatform/setup" + "github.com/rubixchain/rubixgoplatform/wrapper/ensweb" +) + +// @Summary Run Unpledge +// @Description This API will initiate self RBT transfer for a specific DID +// @Tags Account +// @ID run-unpledge +// @Accept json +// @Produce json +// @Success 200 {object} model.BasicResponse +// @Router /api/run-unpledge [post] +func (s *Server) RunUnpledgeHandle(req *ensweb.Request) *ensweb.Result { + var resp model.BasicResponse + + err := s.c.InititateUnpledgeProcess() + if err != nil { + errMsg := fmt.Sprintf("%v: %v", setup.APIRunUnpledge, err.Error()) + resp.Status = false + resp.Message = errMsg + + return s.BasicResponse(req, false, errMsg, nil) + } + + resp.Status = true + resp.Message = "Unpledging of pledged tokens is successful" + return s.RenderJSON(req, resp, http.StatusOK) +} diff --git a/setup/setup.go b/setup/setup.go index fbecb49a..1b586879 100644 --- a/setup/setup.go +++ b/setup/setup.go @@ -68,6 +68,10 @@ const ( APIAddExplorer string = "/api/add-explorer" APIRemoveExplorer string = "/api/remove-explorer" APIAddPeerDetails string = "/api/add-peer-details" + APIGetPledgedTokenDetails string = "/api/get-pledgedtoken-details" + APICheckPinnedState string = "/api/check-pinned-state" + APISelfTransfer string = "/api/initiate-self-transfer" + APIRunUnpledge string = "/api/run-unpledge" ) // jwt.RegisteredClaims diff --git a/tests/node/actions.py b/tests/node/actions.py index 6cb33ef4..6c702e91 100644 --- a/tests/node/actions.py +++ b/tests/node/actions.py @@ -94,9 +94,7 @@ def create_and_register_did(config: dict, did_alias: str, did_type: int = 4, reg did = cmd_create_did(config["server"], config["grpcPort"], did_type) print(f"DID {did} has been created successfully") - config["dids"] = { - did_alias: did - } + config["dids"][did_alias] = did if register_did: cmd_register_did(did, config["server"], config["grpcPort"]) diff --git a/tests/run.py b/tests/run.py index 2a3cce09..354d6f64 100644 --- a/tests/run.py +++ b/tests/run.py @@ -8,7 +8,7 @@ from scenarios import ( rbt_transfer, - bip39_nlss_test, + bip39_nlss_test ) IPFS_KUBO_VERSION = "v0.21.0" @@ -136,27 +136,28 @@ def cli(): if os_name is None: exit(1) - if not skip_prerequisite: - os.chdir("../") - print(f"Building Rubix binary for {os_name}\n") - build_command = "" - if os_name == "Linux": - build_command = "make compile-linux" - elif os_name == "Windows": - build_command = "make compile-windows" - elif os_name == "Darwin": - build_command = "make compile-mac" - - output, code = run_command(build_command) - if code != 0: - print("build failed with error:", output) - exit(1) - else: - print("\nBuild successful\n") + os.chdir("../") + print(f"Building Rubix binary for {os_name}\n") + build_command = "" + if os_name == "Linux": + build_command = "make compile-linux" + elif os_name == "Windows": + build_command = "make compile-windows" + elif os_name == "Darwin": + build_command = "make compile-mac" + + output, code = run_command(build_command) + if code != 0: + print("build failed with error:", output) + exit(1) + else: + print("\nBuild successful\n") + if not skip_prerequisite: download_ipfs_binary(os_name, IPFS_KUBO_VERSION, build_folder) copy_fixtures_to_build_dir(build_folder) - os.chdir("./tests") + + os.chdir("./tests") run_quorum_nodes(run_nodes_only, skip_adding_quorums=skip_adding_quorums) From ef02ead93655b051ead8d657dc000313209f2760 Mon Sep 17 00:00:00 2001 From: Arnab Ghose Date: Thu, 11 Jul 2024 19:06:24 +0530 Subject: [PATCH 089/129] tests: generation of random test swarmkey when tests are run --- tests/run.py | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/tests/run.py b/tests/run.py index 354d6f64..ec57ee02 100644 --- a/tests/run.py +++ b/tests/run.py @@ -3,6 +3,7 @@ import shutil import requests import argparse +import binascii from node.commands import run_command from node.quorum import run_quorum_nodes @@ -13,6 +14,20 @@ IPFS_KUBO_VERSION = "v0.21.0" +def generate_ipfs_swarm_key(build_name): + try: + key = os.urandom(32) + except Exception as e: + print("While trying to read random source:", e) + return + + output = "/key/swarm/psk/1.0.0/\n/base16/\n" + binascii.hexlify(key).decode() + + filename = f"./fixtures/testswarm_{build_name}.key" + + with open(filename, "w") as file: + file.write(output) + def get_os_info(): os_name = platform.system() build_folder = "" @@ -136,6 +151,8 @@ def cli(): if os_name is None: exit(1) + generate_ipfs_swarm_key(build_folder) + os.chdir("../") print(f"Building Rubix binary for {os_name}\n") build_command = "" From 7f52b6b2b98048e8612083ebccb8dbc69aef4c0c Mon Sep 17 00:00:00 2001 From: Arnab Ghose Date: Thu, 11 Jul 2024 19:54:45 +0530 Subject: [PATCH 090/129] fixed pledging period --- core/unpledge.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/unpledge.go b/core/unpledge.go index a04d8b6f..386d0bd3 100644 --- a/core/unpledge.go +++ b/core/unpledge.go @@ -16,7 +16,7 @@ import ( ) const UnpledgeQueueTable string = "unpledgequeue" -const pledgePeriodInSeconds int = 100 //7 * 24 * 60 * 60 +const pledgePeriodInSeconds int = 7 * 24 * 60 * 60 // Pledging period: 7 days type TransTokenBlock struct { TokenID string `json:"token_id"` From a625f8cfd07661749eca681955c83563b9eae3ee Mon Sep 17 00:00:00 2001 From: Maneesha-rubix Date: Thu, 11 Jul 2024 20:47:12 +0530 Subject: [PATCH 091/129] add initiator sign to block and other fixes --- block/block.go | 30 +++++++------- contract/contract.go | 1 + core/quorum_initiator.go | 77 +++++++++++++++++++++++++---------- core/wallet/smart_contract.go | 10 +---- 4 files changed, 72 insertions(+), 46 deletions(-) diff --git a/block/block.go b/block/block.go index 074e3bcd..272d8ee8 100644 --- a/block/block.go +++ b/block/block.go @@ -58,17 +58,17 @@ const ( ) type TokenChainBlock struct { - TransactionType string `json:"transactionType"` - TokenOwner string `json:"owner"` - GenesisBlock *GenesisBlock `json:"genesisBlock"` - TransInfo *TransInfo `json:"transInfo"` - PledgeDetails []PledgeDetail `json:"pledgeDetails"` - QuorumSignature []CreditSignature `json:"quorumSignature"` - SmartContract []byte `json:"smartContract"` - SmartContractData string `json:"smartContractData"` - TokenValue float64 `json:"tokenValue"` - ChildTokens []string `json:"childTokens"` - SenderSignature *SenderSignature `json:"senderSignature"` + TransactionType string `json:"transactionType"` + TokenOwner string `json:"owner"` + GenesisBlock *GenesisBlock `json:"genesisBlock"` + TransInfo *TransInfo `json:"transInfo"` + PledgeDetails []PledgeDetail `json:"pledgeDetails"` + QuorumSignature []CreditSignature `json:"quorumSignature"` + SmartContract []byte `json:"smartContract"` + SmartContractData string `json:"smartContractData"` + TokenValue float64 `json:"tokenValue"` + ChildTokens []string `json:"childTokens"` + InitiatorSignature *InitiatorSignature `json:"initiatorSignature"` } type PledgeDetail struct { @@ -93,10 +93,10 @@ type CreditSignature struct { SignType string `json:"sign_type"` //represents sign type (PkiSign == 0 or NlssSign==1) } -type SenderSignature struct { +type InitiatorSignature struct { NLSS_share string `json:"nlss_share_signature"` Private_sign string `json:"priv_signature"` - DID string `json:"sender_did"` + DID string `json:"initiator_did"` Hash string `json:"hash"` SignType int `json:"sign_type"` //represents sign type (PkiSign == 0 or NlssSign==1) } @@ -169,8 +169,8 @@ func CreateNewBlock(ctcb map[string]*Block, tcb *TokenChainBlock) *Block { if tcb.SmartContractData != "" { ntcb[TCSmartContractDataKey] = tcb.SmartContractData } - if tcb.SenderSignature != nil { - ntcb[TCSenderSignatureKey] = tcb.SenderSignature + if tcb.InitiatorSignature != nil { + ntcb[TCSenderSignatureKey] = tcb.InitiatorSignature } if floatPrecisionToMaxDecimalPlaces(tcb.TokenValue) > floatPrecisionToMaxDecimalPlaces(0) { diff --git a/contract/contract.go b/contract/contract.go index d19334e3..f1632056 100644 --- a/contract/contract.go +++ b/contract/contract.go @@ -444,6 +444,7 @@ func (c *Contract) VerifySignature(dc did.DIDCrypto) error { return err } + fmt.Println("did:", didstr, "\n hash:", hs, "\n share sig:", ss, "\n prv sig:", ps) //If the ss i.e., share signature is empty, then its a Pki sign, so call PvtVerify //Else it is NLSS based sign, so call NlssVerify didType := dc.GetSignType() diff --git a/core/quorum_initiator.go b/core/quorum_initiator.go index d1750a93..cb3e8b7d 100644 --- a/core/quorum_initiator.go +++ b/core/quorum_initiator.go @@ -1058,6 +1058,21 @@ func (c *Core) pledgeQuorumToken(cr *ConensusRequest, sc *contract.Contract, tid if cr.Mode == SmartContractDeployMode { bti.DeployerDID = sc.GetDeployerDID() + //Fetching deployer signature to add it to transaction details + sign_data, deployer_share_sign, deployer_priv_sign, err := sc.GetHashSig(bti.DeployerDID) + if err != nil { + c.log.Error("failed to fetch deployer sign", "err", err) + return nil, fmt.Errorf("failed to fetch deployer sign") + } + deployer_sign_type := dc.GetSignType() + deployer_sign := &block.InitiatorSignature{ + NLSS_share: deployer_share_sign, + Private_sign: deployer_priv_sign, + DID: bti.DeployerDID, + Hash: sign_data, + SignType: deployer_sign_type, + } + var smartContractTokenValue float64 commitedTokens := sc.GetCommitedTokensInfo() @@ -1082,24 +1097,42 @@ func (c *Core) pledgeQuorumToken(cr *ConensusRequest, sc *contract.Contract, tid } tcb = block.TokenChainBlock{ - TransactionType: block.TokenGeneratedType, - TokenOwner: sc.GetDeployerDID(), - TransInfo: bti, - QuorumSignature: credit, - SmartContract: sc.GetBlock(), - GenesisBlock: smartContractGensisBlock, - PledgeDetails: ptds, + TransactionType: block.TokenDeployedType, + TokenOwner: sc.GetDeployerDID(), + TransInfo: bti, + QuorumSignature: credit, + SmartContract: sc.GetBlock(), + GenesisBlock: smartContractGensisBlock, + PledgeDetails: ptds, + InitiatorSignature: deployer_sign, } } else if cr.Mode == SmartContractExecuteMode { bti.ExecutorDID = sc.GetExecutorDID() + + //Fetching executor signature to add it to transaction details + sign_data, executor_share_sign, executor_priv_sign, err := sc.GetHashSig(bti.ExecutorDID) + if err != nil { + c.log.Error("failed to fetch executor sign", "err", err) + return nil, fmt.Errorf("failed to fetch executor sign") + } + executor_sign_type := dc.GetSignType() + executor_sign := &block.InitiatorSignature{ + NLSS_share: executor_share_sign, + Private_sign: executor_priv_sign, + DID: bti.ExecutorDID, + Hash: sign_data, + SignType: executor_sign_type, + } + tcb = block.TokenChainBlock{ - TransactionType: block.TokenGeneratedType, - TokenOwner: sc.GetExecutorDID(), - TransInfo: bti, - QuorumSignature: credit, - SmartContract: sc.GetBlock(), - PledgeDetails: ptds, - SmartContractData: sc.GetSmartContractData(), + TransactionType: block.TokenExecutedType, + TokenOwner: sc.GetExecutorDID(), + TransInfo: bti, + QuorumSignature: credit, + SmartContract: sc.GetBlock(), + PledgeDetails: ptds, + SmartContractData: sc.GetSmartContractData(), + InitiatorSignature: executor_sign, } } else { //Fetching sender signature to add it to transaction details @@ -1110,7 +1143,7 @@ func (c *Core) pledgeQuorumToken(cr *ConensusRequest, sc *contract.Contract, tid return nil, fmt.Errorf("failed to fetch sender sign") } sender_sign_type := dc.GetSignType() - sender_sign := &block.SenderSignature{ + sender_sign := &block.InitiatorSignature{ NLSS_share: sender_share_sign, Private_sign: sender_priv_sign, DID: senderdid, @@ -1121,13 +1154,13 @@ func (c *Core) pledgeQuorumToken(cr *ConensusRequest, sc *contract.Contract, tid bti.SenderDID = sc.GetSenderDID() bti.ReceiverDID = sc.GetReceiverDID() tcb = block.TokenChainBlock{ - TransactionType: block.TokenTransferredType, - TokenOwner: sc.GetReceiverDID(), - TransInfo: bti, - QuorumSignature: credit, - SmartContract: sc.GetBlock(), - PledgeDetails: ptds, - SenderSignature: sender_sign, + TransactionType: block.TokenTransferredType, + TokenOwner: sc.GetReceiverDID(), + TransInfo: bti, + QuorumSignature: credit, + SmartContract: sc.GetBlock(), + PledgeDetails: ptds, + InitiatorSignature: sender_sign, } } diff --git a/core/wallet/smart_contract.go b/core/wallet/smart_contract.go index 19830d76..a37d4c86 100644 --- a/core/wallet/smart_contract.go +++ b/core/wallet/smart_contract.go @@ -49,14 +49,6 @@ func (w *Wallet) GetSmartContractToken(smartContractToken string) ([]SmartContra return nil, fmt.Errorf("no smart contract token is available to commit") } - for i := range sc { - sc[i].ContractStatus = TokenIsGenerated - err := w.s.Update(SmartContractStorage, &sc[i], "smart_contract_hash=?", sc[i].SmartContractHash) - if err != nil { - return nil, err - } - } - return sc, nil } @@ -64,7 +56,7 @@ func (w *Wallet) GetSmartContractTokenByDeployer(did string) ([]SmartContract, e w.dtl.Lock() defer w.dtl.Unlock() var sc []SmartContract - err := w.s.Read(SmartContractStorage, &sc, "did=?", did) + err := w.s.Read(SmartContractStorage, &sc, "deployer=?", did) if err != nil { return nil, err } From 790eec24cb0d2b5c1e00e41b90b9d1dbf6503bbc Mon Sep 17 00:00:00 2001 From: Arnab Ghose Date: Fri, 12 Jul 2024 09:43:35 +0530 Subject: [PATCH 092/129] shifted the update logic of token state hash of tokens in TokensTable inside the TokenReceiver func, to remove the additional update operation --- core/quorum_recv.go | 23 ++------------ core/wallet/token.go | 71 ++++++++++++++++++++++++++++++-------------- 2 files changed, 51 insertions(+), 43 deletions(-) diff --git a/core/quorum_recv.go b/core/quorum_recv.go index 392e6b5e..5fb20271 100644 --- a/core/quorum_recv.go +++ b/core/quorum_recv.go @@ -762,31 +762,13 @@ func (c *Core) updateReceiverToken(req *ensweb.Request) *ensweb.Result { } senderPeerId, _, _ := util.ParseAddress(sr.Address) - err = c.w.TokensReceived(did, sr.TokenInfo, b, senderPeerId, c.peerID) + updatedTokenStateHashes, err := c.w.TokensReceived(did, sr.TokenInfo, b, senderPeerId, c.peerID, c.ipfs) if err != nil { c.log.Error("Failed to update token status", "err", err) crep.Message = "Failed to update token status" return c.l.RenderJSON(req, &crep, http.StatusOK) } - //add to ipfs to get latest Token State Hash after receiving the token by receiver. The hashes will be returned to sender, and from there to - //quorums using pledgefinality function, to be added to TokenStateHash Table - var updatedtokenhashes []string - var tokenwithtokenhash []string - for _, ti := range sr.TokenInfo { - t := ti.Token - b := c.w.GetLatestTokenBlock(ti.Token, ti.TokenType) - blockId, _ := b.GetBlockID(t) - tokenIDTokenStateData := t + blockId - tokenIDTokenStateBuffer := bytes.NewBuffer([]byte(tokenIDTokenStateData)) - tokenIDTokenStateHash, _ := c.ipfs.Add(tokenIDTokenStateBuffer, ipfsnode.Pin(false), ipfsnode.OnlyHash(true)) - updatedtokenhashes = append(updatedtokenhashes, tokenIDTokenStateHash) - tokenwithtokenhash = append(tokenwithtokenhash, t+"."+tokenIDTokenStateHash) - } - - //Updating the latest tokenstatehash with the new owner i.e. receiver - c.w.TokenStateHashUpdate(tokenwithtokenhash) - sc := contract.InitContract(b.GetSmartContract(), nil) if sc == nil { c.log.Error("Failed to update token status, missing smart contract") @@ -819,7 +801,8 @@ func (c *Core) updateReceiverToken(req *ensweb.Request) *ensweb.Result { for _, qrm := range sr.QuorumInfo { c.w.AddDIDPeerMap(qrm.DID, qrm.PeerID, *qrm.DIDType) } - crep.Result = updatedtokenhashes + + crep.Result = updatedTokenStateHashes return c.l.RenderJSON(req, &crep, http.StatusOK) } diff --git a/core/wallet/token.go b/core/wallet/token.go index fbd6c8de..d12ffb1b 100644 --- a/core/wallet/token.go +++ b/core/wallet/token.go @@ -4,10 +4,12 @@ import ( "fmt" "os" "strings" + "bytes" "github.com/rubixchain/rubixgoplatform/block" "github.com/rubixchain/rubixgoplatform/contract" "github.com/rubixchain/rubixgoplatform/util" + ipfsnode "github.com/ipfs/go-ipfs-api" ) const ( @@ -376,13 +378,29 @@ func (w *Wallet) TokensTransferred(did string, ti []contract.TokenInfo, b *block return nil } -func (w *Wallet) TokensReceived(did string, ti []contract.TokenInfo, b *block.Block, senderPeerId string, receiverPeerId string) error { +func (w *Wallet) TokensReceived(did string, ti []contract.TokenInfo, b *block.Block, senderPeerId string, receiverPeerId string, ipfsShell *ipfsnode.Shell) ([]string, error) { w.l.Lock() defer w.l.Unlock() // TODO :: Needs to be address err := w.CreateTokenBlock(b) if err != nil { - return err + return nil, err + } + + //add to ipfs to get latest Token State Hash after receiving the token by receiver. The hashes will be returned to sender, and from there to + //quorums using pledgefinality function, to be added to TokenStateHash Table + var updatedtokenhashes []string = make([]string, 0) + var tokenHashMap map[string]string = make(map[string]string) + + for _, info := range ti { + t := info.Token + b := w.GetLatestTokenBlock(info.Token, info.TokenType) + blockId, _ := b.GetBlockID(t) + tokenIDTokenStateData := t + blockId + tokenIDTokenStateBuffer := bytes.NewBuffer([]byte(tokenIDTokenStateData)) + tokenIDTokenStateHash, _ := ipfsShell.Add(tokenIDTokenStateBuffer, ipfsnode.Pin(false), ipfsnode.OnlyHash(true)) + updatedtokenhashes = append(updatedtokenhashes, tokenIDTokenStateHash) + tokenHashMap[t] = tokenIDTokenStateHash } for i := range ti { @@ -393,45 +411,52 @@ func (w *Wallet) TokensReceived(did string, ti []contract.TokenInfo, b *block.Bl err := util.CreateDir(dir) if err != nil { w.log.Error("Faled to create directory", "err", err) - return err + return nil, err } defer os.RemoveAll(dir) err = w.Get(ti[i].Token, did, OwnerRole, dir) if err != nil { w.log.Error("Faled to get token", "err", err) - return err + return nil, err } gb := w.GetGenesisTokenBlock(ti[i].Token, ti[i].TokenType) pt := "" if gb != nil { pt, _, _ = gb.GetParentDetials(ti[i].Token) } + + tokenId := ti[i].Token + t = Token{ - TokenID: ti[i].Token, + TokenID: tokenId, TokenValue: ti[i].TokenValue, ParentTokenID: pt, DID: did, } + t.TokenStateHash = tokenHashMap[tokenId] + err = w.s.Write(TokenStorage, &t) if err != nil { - return err + return nil, err } } t.DID = did t.TokenStatus = TokenIsFree + t.TokenStateHash = tokenHashMap[t.TokenID] + err = w.s.Update(TokenStorage, &t, "token_id=?", ti[i].Token) if err != nil { - return err + return nil, err } senderAddress := senderPeerId + "." + b.GetSenderDID() receiverAddress := receiverPeerId + "." + b.GetReceiverDID() //Pinnig the whole tokens and pat tokens ok, err := w.Pin(ti[i].Token, OwnerRole, did, b.GetTid(), senderAddress, receiverAddress, ti[i].TokenValue) if err != nil { - return err + return nil, err } if !ok { - return fmt.Errorf("failed to pin token") + return nil, fmt.Errorf("failed to pin token") } } // for i := range pt { @@ -451,22 +476,22 @@ func (w *Wallet) TokensReceived(did string, ti []contract.TokenInfo, b *block.Bl // t.TokenStatus = TokenIsTransferred // w.AddTokenBlock(pt[i], tcb) // } - return nil + return updatedtokenhashes, nil } -func (w *Wallet) TokenStateHashUpdate(tokenwithtokenhash []string) { - w.l.Lock() - defer w.l.Unlock() - var t Token - for _, val := range tokenwithtokenhash { - token := strings.Split(val, ".")[0] - tokenstatehash := strings.Split(val, ".")[1] - _ = w.s.Read(TokenStorage, &t, "token_id=?", token) - t.TokenStateHash = tokenstatehash - _ = w.s.Update(TokenStorage, &t, "token_id=?", token) - } - -} +// func (w *Wallet) TokenStateHashUpdate(tokenwithtokenhash []string) { +// w.l.Lock() +// defer w.l.Unlock() +// var t Token +// for _, val := range tokenwithtokenhash { +// token := strings.Split(val, ".")[0] +// tokenstatehash := strings.Split(val, ".")[1] +// _ = w.s.Read(TokenStorage, &t, "token_id=?", token) +// t.TokenStateHash = tokenstatehash +// _ = w.s.Update(TokenStorage, &t, "token_id=?", token) +// } + +// } func (w *Wallet) CommitTokens(did string, rbtTokens []string) error { w.l.Lock() From a6074b96c59e3eb69d84e2480095d739fa84dbed Mon Sep 17 00:00:00 2001 From: Arnab Ghose Date: Fri, 12 Jul 2024 10:36:29 +0530 Subject: [PATCH 093/129] tests: added random swarm key generation --- tests/run.py | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/tests/run.py b/tests/run.py index 2a3cce09..67e41e2f 100644 --- a/tests/run.py +++ b/tests/run.py @@ -3,6 +3,7 @@ import shutil import requests import argparse +import binascii from node.commands import run_command from node.quorum import run_quorum_nodes @@ -13,6 +14,21 @@ IPFS_KUBO_VERSION = "v0.21.0" + +def generate_ipfs_swarm_key(build_name): + try: + key = os.urandom(32) + except Exception as e: + print("While trying to read random source:", e) + return + + output = "/key/swarm/psk/1.0.0/\n/base16/\n" + binascii.hexlify(key).decode() + + filename = f"./fixtures/testswarm_{build_name}.key" + + with open(filename, "w") as file: + file.write(output) + def get_os_info(): os_name = platform.system() build_folder = "" From f1b8a713940afa6ea6376ed044803c917904c53a Mon Sep 17 00:00:00 2001 From: Maneesha-rubix Date: Fri, 12 Jul 2024 10:53:53 +0530 Subject: [PATCH 094/129] removing unnecessary log --- contract/contract.go | 1 - 1 file changed, 1 deletion(-) diff --git a/contract/contract.go b/contract/contract.go index f1632056..d19334e3 100644 --- a/contract/contract.go +++ b/contract/contract.go @@ -444,7 +444,6 @@ func (c *Contract) VerifySignature(dc did.DIDCrypto) error { return err } - fmt.Println("did:", didstr, "\n hash:", hs, "\n share sig:", ss, "\n prv sig:", ps) //If the ss i.e., share signature is empty, then its a Pki sign, so call PvtVerify //Else it is NLSS based sign, so call NlssVerify didType := dc.GetSignType() From 8a80a32181f7db4127bdbe41783e33743693918f Mon Sep 17 00:00:00 2001 From: Arnab Ghose Date: Fri, 12 Jul 2024 10:56:00 +0530 Subject: [PATCH 095/129] fix: removed token count check from main initiateRBTTransfer func --- tests/scenarios/periodic_pledging.py | 79 ++++++++++++++++++++++++++++ 1 file changed, 79 insertions(+) create mode 100644 tests/scenarios/periodic_pledging.py diff --git a/tests/scenarios/periodic_pledging.py b/tests/scenarios/periodic_pledging.py new file mode 100644 index 00000000..9336ae01 --- /dev/null +++ b/tests/scenarios/periodic_pledging.py @@ -0,0 +1,79 @@ +from node.actions import rbt_transfer, fund_did_with_rbt, setup_rubix_nodes, \ + create_and_register_did, add_quorums, add_peer_details +from node.utils import get_did_by_alias +from config.utils import save_to_config_file, load_from_config_file +from helper.utils import expect_failure, expect_success +from node.quorum import get_quorum_config + +__node_config_path = "./periodic_pledging.json" + +def setup(): + print("Setting up test.....") + print("Configuring and running node15 and node16...") + + node_config = setup_rubix_nodes("periodic_pledging") + + config_A = node_config["node15"] + config_B = node_config["node16"] + + create_and_register_did(config_A, "did_a", register_did=False) + create_and_register_did(config_A, "did_a1", register_did=False) + create_and_register_did(config_B, "did_b", register_did=False) + + save_to_config_file(__node_config_path, node_config) + + print("Adding quorums") + add_quorums(node_config) + + print("Setup Done\n") + return node_config + +def run(skip_setup: bool = False): + print("\n----------- 1. Running Tests related to Periodic Pledging -----------\n") + node_config = {} + + # In some cases, we may wish to run tests for an existing test configuration + # where the nodes are running already. If skip_setup is True, the setup steps + # are skipped and we proceed to directly run the test cases and load the config + # from the config file + if not skip_setup: + node_config = setup() + else: + node_config = load_from_config_file(__node_config_path) + add_quorums(node_config) + + shuttle_transfer(node_config) + + print("\n-------------- Tests Completed -------------------\n") + +def shuttle_transfer(config): + node_A_info, node_B_info = config["node15"], config["node16"] + server_port_A, grpc_port_A = node_A_info["server"], node_A_info["grpcPort"] + server_port_B, grpc_port_B = node_B_info["server"], node_B_info["grpcPort"] + did_A, did_B = get_did_by_alias(node_A_info, "did_a"), get_did_by_alias(node_B_info, "did_b") + + quorum_config = get_quorum_config() + + for _, val in quorum_config.items(): + add_peer_details(val["peerId"], val["dids"]["did_quorum"], 4, server_port_A, grpc_port_A) + add_peer_details(val["peerId"], val["dids"]["did_quorum"], 4, server_port_B, grpc_port_B) + + print("------ Test Case (PASS): Shuttle transfer started ------\n") + + print("\n1. Generating 3 whole RBT for A") + expect_success(fund_did_with_rbt)(node_A_info, did_A, 4) + print("Funded node A with 4 RBT") + + print("\n2. Transferring 3 RBT from A to B....") + add_peer_details(node_B_info["peerId"], did_B, 4, server_port_A, grpc_port_A) + expect_success(rbt_transfer)(did_A, did_B, 3, server_port_A, grpc_port_A) + print("Transferred 3 RBT from A to B") + + # print("Waiting for 80 seconds before ") + # time.sleep(80) + + # print("\n3. Transferring 3 RBT from A to A1....") + # expect_success(rbt_transfer)(address_B, address_A1, 3, server_port_B, grpc_port_B) + # print("Transferred 3 RBT from A to A1") + + print("\n------ Test Case (PASS): Shuttle transfer completed ------\n") From a782594db0e7c01b995851e0d8d0da33d37690cd Mon Sep 17 00:00:00 2001 From: Arnab Ghose Date: Fri, 12 Jul 2024 11:32:50 +0530 Subject: [PATCH 096/129] token count condition fix --- core/transfer.go | 4 ---- 1 file changed, 4 deletions(-) diff --git a/core/transfer.go b/core/transfer.go index 5a3ab302..ab84a43b 100644 --- a/core/transfer.go +++ b/core/transfer.go @@ -181,10 +181,6 @@ func (c *Core) initiateRBTTransfer(reqID string, req *model.RBTTransferRequest) // This flag indicates if the call is made for Self Transfer or general token transfer isSelfRBTTransfer := senderDID == receiverdid - if req.TokenCount < MinDecimalValue(MaxDecimalPlaces) { - resp.Message = "Input transaction amount is less than minimum transaction amount" - return resp - } dc, err := c.SetupDID(reqID, senderDID) if err != nil { From 172593226a3b3dc621df0f8a34fcafa8b361f9f6 Mon Sep 17 00:00:00 2001 From: Arnab Ghose Date: Fri, 12 Jul 2024 12:18:50 +0530 Subject: [PATCH 097/129] fixed the pledge period variable --- core/transfer.go | 3 +-- core/unpledge/unpledge.go | 2 -- 2 files changed, 1 insertion(+), 4 deletions(-) diff --git a/core/transfer.go b/core/transfer.go index ab84a43b..1490a8d8 100644 --- a/core/transfer.go +++ b/core/transfer.go @@ -8,7 +8,6 @@ import ( "github.com/rubixchain/rubixgoplatform/contract" "github.com/rubixchain/rubixgoplatform/core/model" - "github.com/rubixchain/rubixgoplatform/core/unpledge" "github.com/rubixchain/rubixgoplatform/core/wallet" "github.com/rubixchain/rubixgoplatform/did" "github.com/rubixchain/rubixgoplatform/wrapper/uuid" @@ -101,7 +100,7 @@ func gatherTokensForTransaction(c *Core, req *model.RBTTransferRequest, dc did.D return nil, fmt.Errorf("failed to get transaction details for trx hash: %v, err: %v", token.TransactionID, err) } - if time.Now().Unix() - tokenTransactionDetail.Epoch > int64(unpledge.PledgePeriodInSeconds) { + if time.Now().Unix() - tokenTransactionDetail.Epoch > int64(pledgePeriodInSeconds) { if err := c.w.LockToken(&token); err != nil { return nil, fmt.Errorf("failed to lock tokens %v, exiting selfTransfer routine with error: %v", token.TokenID, err.Error()) } diff --git a/core/unpledge/unpledge.go b/core/unpledge/unpledge.go index 9cdc4448..63fd8134 100644 --- a/core/unpledge/unpledge.go +++ b/core/unpledge/unpledge.go @@ -9,8 +9,6 @@ import ( ) const ( - PledgePeriodInSeconds int = 7 * 24 * 60 * 60 - UnpledgeQueueTable string = "unpledgequeue" ) From be28e17fed630b18355df390d2a7412709a88a93 Mon Sep 17 00:00:00 2001 From: Arnab Ghose Date: Fri, 12 Jul 2024 15:31:44 +0530 Subject: [PATCH 098/129] added check to skip tokens, part of PoW pledging, for self transfer operation --- core/transfer.go | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/core/transfer.go b/core/transfer.go index 1490a8d8..1f05dc57 100644 --- a/core/transfer.go +++ b/core/transfer.go @@ -95,6 +95,11 @@ func gatherTokensForTransaction(c *Core, req *model.RBTTransferRequest, dc did.D // Get the transaction epoch for every token and chec for _, token := range tokensOwnedBySender { + // Nodes running old version of rubixgoplatform will not have their TransactionID column of Tokens's table populated + // And hence should be skipped from Self Transfer + if token.TransactionID == "" { + continue + } tokenTransactionDetail, err := c.w.GetTransactionDetailsbyTransactionId(token.TransactionID) if err != nil { return nil, fmt.Errorf("failed to get transaction details for trx hash: %v, err: %v", token.TransactionID, err) @@ -285,7 +290,15 @@ func (c *Core) initiateRBTTransfer(reqID string, req *model.RBTTransferRequest) } et := time.Now() dif := et.Sub(st) - td.Amount = req.TokenCount + if isSelfRBTTransfer { + var amt float64 = 0 + for _, tknInfo := range tis { + amt += tknInfo.TokenValue + } + td.Amount = amt + } else { + td.Amount = req.TokenCount + } td.TotalTime = float64(dif.Milliseconds()) if err := c.w.AddTransactionHistory(td); err != nil { From e3cc03e6287ed3bf240bbff4eb64f6308535ed6d Mon Sep 17 00:00:00 2001 From: harirubix Date: Wed, 17 Jul 2024 21:12:50 +0530 Subject: [PATCH 099/129] fix for quorum length 5 to 7 --- core/quorum.go | 12 ++++++------ core/quorum_initiator.go | 4 ++-- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/core/quorum.go b/core/quorum.go index e7489762..57bc6a5e 100644 --- a/core/quorum.go +++ b/core/quorum.go @@ -82,25 +82,25 @@ func (qm *QuorumManager) GetQuorum(t int, lastChar string) []string { return nil } var quorumAddrList []string - quorumCount := 0 + quorumAddrCount := 0 for _, q := range quorumList { addr := string(q.PeerID + "." + q.DID) quorumAddrList = append(quorumAddrList, addr) - quorumCount = quorumCount + 1 - if quorumCount == 7 { + quorumAddrCount = quorumAddrCount + 1 + if quorumAddrCount == 7 { break } } return quorumAddrList case QuorumTypeTwo: var quorumAddrList []string - quorumCount := 0 + quorumAddrCount := 0 for _, q := range qm.ql { peerID := qm.GetPeerID(q) addr := string(peerID + "." + q) quorumAddrList = append(quorumAddrList, addr) - quorumCount = quorumCount + 1 - if quorumCount == 7 { + quorumAddrCount = quorumAddrCount + 1 + if quorumAddrCount == 7 { break } } diff --git a/core/quorum_initiator.go b/core/quorum_initiator.go index cb3e8b7d..15421c96 100644 --- a/core/quorum_initiator.go +++ b/core/quorum_initiator.go @@ -364,8 +364,8 @@ func (c *Core) initiateConsensus(cr *ConensusRequest, sc *contract.Contract, dc delete(c.pd, cr.ReqID) c.qlock.Unlock() }() - c.quorumCount = 0 - c.noBalanceQuorumCount = 0 + c.quorumCount = QuorumRequired - len(cr.QuorumList) + c.noBalanceQuorumCount = QuorumRequired - len(cr.QuorumList) for _, a := range cr.QuorumList { //This part of code is trying to connect to the quorums in quorum list, where various functions are called to pledge the tokens //and checking of transaction by the quorum i.e. consensus for the transaction. Once the quorum is connected, it pledges and From d5d39f60765f914054b4eeba7e23beea91a394d5 Mon Sep 17 00:00:00 2001 From: Arnab Ghose Date: Mon, 22 Jul 2024 09:58:48 +0530 Subject: [PATCH 100/129] added CLI/API to unpledge POW based pledge tokens and drop the unpledgequeue table present in rubixgoplatform node versions v0.0.17 and earlier --- .gitignore | 6 +- client/unpledge.go | 10 + command/command.go | 5 + command/unpledge.go | 14 +- core/core.go | 7 - core/migrate.go | 2 +- core/peer.go | 2 +- core/quorum.go | 36 +++- core/quorum_initiator.go | 3 +- core/quorum_recv.go | 22 +- core/self_transfer.go | 250 ---------------------- core/storage/storage.go | 1 + core/storage/storage_db.go | 5 + core/unpledge.go | 419 ++++++++++++++----------------------- core/unpledge/unpledge.go | 90 -------- core/wallet/credit.go | 48 +++-- core/wallet/unpledge.go | 98 +++++++++ core/wallet/wallet.go | 7 + docs/docs.go | 26 ++- docs/swagger.json | 26 ++- docs/swagger.yaml | 19 +- server/server.go | 1 + server/unpledge.go | 26 ++- setup/setup.go | 1 + 24 files changed, 484 insertions(+), 640 deletions(-) delete mode 100644 core/self_transfer.go delete mode 100644 core/unpledge/unpledge.go create mode 100644 core/wallet/unpledge.go diff --git a/.gitignore b/.gitignore index 9f8b4b91..cbaf76d2 100644 --- a/.gitignore +++ b/.gitignore @@ -29,5 +29,9 @@ mac/ windows/ dist/ +testswarm_linux.key +testswarm_windows.key +testswarm_mac.key + # used for testing purpose -!node_registry.json \ No newline at end of file +!node_registry.json diff --git a/client/unpledge.go b/client/unpledge.go index aababe4e..c2e4161f 100644 --- a/client/unpledge.go +++ b/client/unpledge.go @@ -14,3 +14,13 @@ func (c *Client) RunUnpledge() (string, bool) { return resp.Message, resp.Status } + +func (c *Client) UnpledgePOWBasedPledgedTokens() (string, bool) { + var resp model.BasicResponse + err := c.sendJSONRequest("POST", setup.APIUnpledgePOWPledgeTokens, nil, struct{}{}, &resp) + if err != nil { + return err.Error(), false + } + + return resp.Message, resp.Status +} diff --git a/command/command.go b/command/command.go index c77fe0fc..72dc1aa4 100644 --- a/command/command.go +++ b/command/command.go @@ -87,6 +87,7 @@ const ( CheckPinnedState string = "checkpinnedstate" SelfTransferRBT string = "self-transfer-rbt" RunUnpledge string = "run-unpledge" + UnpledgePOWPledgeTokens string = "unpledge-pow-pledge-tokens" ) var commands = []string{VersionCmd, @@ -135,6 +136,7 @@ var commands = []string{VersionCmd, AddPeerDetailsCmd, SelfTransferRBT, RunUnpledge, + UnpledgePOWPledgeTokens, } var commandsHelp = []string{"To get tool version", @@ -183,6 +185,7 @@ var commandsHelp = []string{"To get tool version", "This command is to add the peer details manually", "This command will initiate a self RBT transfer", "This command will unpledge all the pledged tokens", + "This command will unpledge all PoW based pledge tokens and drop the unpledgequeue table", } type Command struct { @@ -626,6 +629,8 @@ func Run(args []string) { cmd.SelfTransferRBT() case RunUnpledge: cmd.RunUnpledge() + case UnpledgePOWPledgeTokens: + cmd.UnpledgePOWBasedPledgedTokens() default: cmd.log.Error("Invalid command") } diff --git a/command/unpledge.go b/command/unpledge.go index c74c7c15..2880b160 100644 --- a/command/unpledge.go +++ b/command/unpledge.go @@ -7,5 +7,15 @@ func (cmd *Command) RunUnpledge() { return } - cmd.log.Debug(msg) -} \ No newline at end of file + cmd.log.Info(msg) +} + +func (cmd *Command) UnpledgePOWBasedPledgedTokens() { + msg, status := cmd.c.UnpledgePOWBasedPledgedTokens() + if !status { + cmd.log.Error(msg) + return + } + + cmd.log.Info(msg) +} diff --git a/core/core.go b/core/core.go index 0033aa44..9ee60f6b 100644 --- a/core/core.go +++ b/core/core.go @@ -16,7 +16,6 @@ import ( "github.com/rubixchain/rubixgoplatform/core/pubsub" "github.com/rubixchain/rubixgoplatform/core/service" "github.com/rubixchain/rubixgoplatform/core/storage" - "github.com/rubixchain/rubixgoplatform/core/unpledge" "github.com/rubixchain/rubixgoplatform/core/wallet" "github.com/rubixchain/rubixgoplatform/did" didm "github.com/rubixchain/rubixgoplatform/did" @@ -90,7 +89,6 @@ type Core struct { ipfsState bool ipfsChan chan bool d *did.DID - up *unpledge.UnPledge didDir string pm *ipfsport.PeerManager qm *QuorumManager @@ -270,11 +268,6 @@ func NewCore(cfg *config.Config, cfgFile string, encKey string, log logger.Logge c.log.Error("Failed to setup quorum manager", "err", err) return nil, err } - c.up, err = unpledge.InitUnPledge(c.s, c.w, c.testNet, c.log) - if err != nil { - c.log.Error("Failed to init unpledge", "err", err) - return nil, err - } if c.arbitaryMode { c.srv, err = service.NewService(c.s, c.as, c.log) if err != nil { diff --git a/core/migrate.go b/core/migrate.go index 48c155ac..1ea21dc7 100644 --- a/core/migrate.go +++ b/core/migrate.go @@ -701,7 +701,7 @@ func (c *Core) migrateNode(reqID string, m *MigrateRequest, didDir string) error c.log.Error("Failed to migrate, failed to marshal credit", "err", err) return fmt.Errorf("failed to migrate, failed to marshal credit") } - err = c.w.StoreCredit(did, base64.StdEncoding.EncodeToString(jb)) + err = c.w.StoreCredit(did, base64.StdEncoding.EncodeToString(jb), nil) if err != nil { c.log.Error("Failed to migrate, failed to store credit", "err", err) return fmt.Errorf("failed to migrate, failed to store credit") diff --git a/core/peer.go b/core/peer.go index c11ed750..99d3e2dd 100644 --- a/core/peer.go +++ b/core/peer.go @@ -92,7 +92,7 @@ func (c *Core) peerStatus(req *ensweb.Request) *ensweb.Result { func (c *Core) getPeer(addr string, self_did string) (*ipfsport.Peer, error) { peerID, did, ok := util.ParseAddress(addr) if !ok { - return nil, fmt.Errorf("invalid address") + return nil, fmt.Errorf("invalid address: %v", addr) } // check if addr contains the peer ID if peerID == "" { diff --git a/core/quorum.go b/core/quorum.go index e7489762..035d161b 100644 --- a/core/quorum.go +++ b/core/quorum.go @@ -1,6 +1,9 @@ package core import ( + "fmt" + "strings" + "github.com/rubixchain/rubixgoplatform/core/storage" "github.com/rubixchain/rubixgoplatform/core/wallet" "github.com/rubixchain/rubixgoplatform/wrapper/logger" @@ -39,6 +42,11 @@ type QuorumData struct { Address string `gorm:"column:address;primaryKey" json:"address"` } +// isOldAddressFormat checks if the address is in . format (followed in versions v0.0.17 and before) +func isOldAddressFormat(address string) bool { + return len(strings.Split(address, ".")) == 2 +} + func NewQuorumManager(s storage.Storage, log logger.Logger) (*QuorumManager, error) { qm := &QuorumManager{ s: s, @@ -54,7 +62,33 @@ func NewQuorumManager(s storage.Storage, log logger.Logger) (*QuorumManager, err if err == nil { qm.ql = make([]string, 0) for _, q := range qd { - qm.ql = append(qm.ql, q.Address) + // Node with version v0.0.17 or prior will have stored the addresses in + // . format. To make it compatible the current implementation, + // we check if its in the prior format, and if its so, then we change it to + // format and update it in quorummanager table + if isOldAddressFormat(q.Address) { + quorumAddressElements := strings.Split(q.Address, ".") + quorumDID := quorumAddressElements[1] + + // Replace the old address format with new format in quorummanager + var updatedQuorumDetails QuorumData = QuorumData{ + Type: q.Type, + Address: quorumDID, + } + err = qm.s.Write(QuorumStorage, &updatedQuorumDetails) + if err != nil { + return nil, fmt.Errorf("failed while writing quorum info with new address format in quorummanager table, err: %v", err) + } + + err := qm.s.Delete(QuorumStorage, &QuorumData{}, "address=?", q.Address) + if err != nil { + return nil, fmt.Errorf("failed while deleting quorum info to replace with new address format in quorummanager table, err: %v", err) + } + + qm.ql = append(qm.ql, quorumDID) + } else { + qm.ql = append(qm.ql, q.Address) + } } } return qm, nil diff --git a/core/quorum_initiator.go b/core/quorum_initiator.go index d3bdd16d..9f4dda39 100644 --- a/core/quorum_initiator.go +++ b/core/quorum_initiator.go @@ -347,6 +347,7 @@ func (c *Core) initiateConsensus(cr *ConensusRequest, sc *contract.Contract, dc c.log.Error("Failed to get required quorums") return nil, nil, fmt.Errorf("failed to get required quorums") } + var finalQl []string var errFQL error if cr.Type == 2 { @@ -1139,7 +1140,7 @@ func (c *Core) connectQuorum(cr *ConensusRequest, addr string, qt int, sc *contr var err error p, err = c.getPeer(addr, sc.GetSenderDID()) if err != nil { - c.log.Error("Failed to get peer connection", "err", err) + c.log.Error(fmt.Sprintf("Failed to get peer connection while connecting to quorum address %v, err: %v", addr, err)) c.finishConsensus(cr.ReqID, qt, nil, false, "", nil, nil) return } diff --git a/core/quorum_recv.go b/core/quorum_recv.go index 044fb8c9..186b0e8d 100644 --- a/core/quorum_recv.go +++ b/core/quorum_recv.go @@ -42,12 +42,20 @@ func (c *Core) addUnpledgeDetails(req *ensweb.Request) *ensweb.Result { return c.l.RenderJSON(req, &resp, http.StatusOK) } - // Add Unpledge details to UnpledgeQueue + // Add Unpledge details to UnpledgeSequence table pledgeTokenHashesStrArr := strings.Join(pledgeTokenHashes, ",") - err := c.up.AddUnPledge(transactionID, pledgeTokenHashesStrArr, transactionEpoch, quorumDID) + + unpledgeSequenceInfo := &wallet.UnpledgeSequenceInfo{ + TransactionID: transactionID, + PledgeTokens: pledgeTokenHashesStrArr, + Epoch: transactionEpoch, + QuorumDID: quorumDID, + } + + err := c.w.AddUnpledgeSequenceInfo(unpledgeSequenceInfo) if err != nil { - resp.Message = fmt.Sprintf("Error while adding record to UnpledgeQueue table for txId: %v, error: %v", transactionID, err.Error()) - c.log.Error(fmt.Sprintf("Error while adding record to UnpledgeQueue table for txId: %v, error: %v", transactionID, err.Error())) + resp.Message = fmt.Sprintf("Error while adding record to UnpledgeSequence table for txId: %v, error: %v", transactionID, err.Error()) + c.log.Error(fmt.Sprintf("Error while adding record to UnpledgeSequence table for txId: %v, error: %v", transactionID, err.Error())) return c.l.RenderJSON(req, &resp, http.StatusOK) } @@ -993,7 +1001,11 @@ func (c *Core) quorumCredit(req *ensweb.Request) *ensweb.Result { crep.Message = "Failed to parse request" return c.l.RenderJSON(req, &crep, http.StatusOK) } - err = c.w.StoreCredit(did, base64.StdEncoding.EncodeToString(jb)) + // TODO: quorumCredit was earlier used to pass QuorumSignature as Credit information + // to other nodes. While working on Credit Restructing, this function would require changes. + // Following nil input to third argument is a temp fix, since quorumCredit is not called anywhere + // in this implementation + err = c.w.StoreCredit(did, base64.StdEncoding.EncodeToString(jb), nil) if err != nil { c.log.Error("Failed to store credit", "err", err) crep.Message = "Failed to store credit" diff --git a/core/self_transfer.go b/core/self_transfer.go deleted file mode 100644 index d9331257..00000000 --- a/core/self_transfer.go +++ /dev/null @@ -1,250 +0,0 @@ -package core - -// import ( -// "fmt" -// "net/http" -// "time" - -// "github.com/rubixchain/rubixgoplatform/contract" -// "github.com/rubixchain/rubixgoplatform/core/model" -// "github.com/rubixchain/rubixgoplatform/core/unpledge" -// "github.com/rubixchain/rubixgoplatform/core/wallet" -// "github.com/rubixchain/rubixgoplatform/did" -// "github.com/rubixchain/rubixgoplatform/wrapper/ensweb" - -// "github.com/rubixchain/rubixgoplatform/wrapper/uuid" -// ) - -// func (c *Core) selfTransferService() { -// c.l.AddRoute(APISelfTransfer, "POST", c.APISelfTransfer) -// } - -// func (c *Core) didResponse(req *ensweb.Request, reqID string) *ensweb.Result { -// dc := c.GetWebReq(reqID) -// ch := <-dc.OutChan -// time.Sleep(time.Millisecond * 10) -// sr, ok := ch.(*did.SignResponse) -// if ok { -// return c.l.RenderJSON(req, sr, http.StatusOK) -// } -// br, ok := ch.(*model.BasicResponse) -// if ok { -// c.RemoveWebReq(reqID) -// br.Status = true -// return c.l.RenderJSON(req, br, http.StatusOK) -// } -// return c.l.RenderJSON(req, &model.BasicResponse{Status: false, Message: "Invalid response"}, http.StatusOK) -// } - -// func (c *Core) APISelfTransfer(req *ensweb.Request) *ensweb.Result { -// resp := model.BasicResponse{ -// Status: false, -// } - -// if req.ID == "" { -// c.log.Debug("Request ID for API Self Transfer not set") -// req.ID = uuid.New().String() -// } - -// var selfTransferReq model.SelfTransferRequest -// err := c.l.ParseJSON(req, &selfTransferReq) -// if err != nil { -// return c.l.RenderJSON(req, resp, http.StatusOK) -// } - -// c.AddWebReq(req) -// go c.initSelfTransfer(req.ID, &selfTransferReq) -// return c.didResponse(req, req.ID) -// } - -// func (c *Core) initSelfTransfer(reqID string, req *model.SelfTransferRequest) { -// br := c.selfTransfer(reqID, req) -// dc := c.GetWebReq(reqID) -// if dc == nil { -// c.log.Error("Failed to get did channels") -// return -// } -// dc.OutChan <- br -// } - - -// func (c *Core) selfTransfer(reqID string, rbtTransferRequest *model.RBTTransferRequest) *model.BasicResponse { -// st := time.Now() - -// response := &model.BasicResponse{ -// Status: false, -// } - -// owner := rbtTransferRequest.Sender - -// c.log.Debug("Initiating Self Trasfer for DID: ", owner) - -// // Get all free tokens -// freeTokensOfOwner, err := c.w.GetFreeTokens(owner) -// if err != nil { -// response.Message = "failed to get free tokens of owner, error: " + err.Error() -// return response -// } - -// // Get the transaction epoch for every token and chec -// var selfTransferredTokens []wallet.Token = make([]wallet.Token, 0) - -// for _, token := range freeTokensOfOwner { -// tokenTransactionDetail, err := c.w.GetTransactionDetailsbyTransactionId(token.TransactionID) -// if err != nil { -// return response -// } - -// if time.Now().Unix() - tokenTransactionDetail.Epoch > int64(unpledge.PledgePeriodInSeconds) { -// if err := c.w.LockToken(&token); err != nil { -// errMsg := fmt.Sprintf("selfTransfer: failed to lock tokens %v, exiting selfTransfer routine with error: %v", token.TokenID, err.Error()) -// c.log.Error(errMsg) -// response.Message = errMsg -// return response -// } - -// selfTransferredTokens = append(selfTransferredTokens, token) -// } -// } - - -// // -------------------------------- - -// // Get details of Tokens -// var ownedTokens []wallet.Token -// for _, token := range tokens { -// walletToken, err := c.w.ReadToken(token) -// if err != nil { -// response.Message = err.Error() -// return response -// } -// ownedTokens = append(ownedTokens, *walletToken) -// } -// defer c.w.ReleaseTokens(ownedTokens) - -// c.log.Debug("1") -// // Lock the free tokens for processing -// for _, ownedToken := range ownedTokens { -// if err := c.w.LockToken(&ownedToken); err != nil { -// errMsg := fmt.Sprintf("selfTransfer: failed to lock tokens %v, exiting selfTransfer routine with error: %v", ownedToken.TokenID, err.Error()) -// c.log.Error(errMsg) -// response.Message = errMsg -// return response -// } -// } - -// selfPeerId := c.GetPeerID() -// selfAddress := selfPeerId + "." + ownerDID -// for i := range ownedTokens { -// c.w.Pin(ownedTokens[i].TokenID, wallet.OwnerRole, ownerDID, "TID-Not Generated", selfAddress, selfAddress, ownedTokens[i].TokenValue) -// } - -// c.log.Debug("2") -// // Setup DID -// dc, err := c.SetupDID(reqID, ownerDID) -// if err != nil { -// response.Message = "Failed to setup DID, " + err.Error() -// c.log.Error(fmt.Sprintf("selfTransfer: failed to setup DID, error: %v", err.Error())) -// return response -// } - -// // Create a Contract for the self transfer -// tokenInfos := make([]contract.TokenInfo, 0) -// totalTokenValue := getTotalValueFromTokens(ownedTokens) - -// c.log.Debug("3") -// for _, freeToken := range ownedTokens { -// tokenTypeString := "rbt" -// if freeToken.TokenValue != 1 { -// tokenTypeString = "part" -// } - -// tokenType := c.TokenType(tokenTypeString) -// latestTokenBlock := c.w.GetLatestTokenBlock(freeToken.TokenID, tokenType) -// if latestTokenBlock == nil { -// c.log.Error("failed to get latest block, invalid token chain") -// response.Message = "failed to get latest block, invalid token chain" -// return response -// } - -// latestBlockID, err := latestTokenBlock.GetBlockID(freeToken.TokenID) -// if err != nil { -// c.log.Error("failed to get block id", "err", err) -// response.Message = "failed to get block id, " + err.Error() -// return response -// } -// tokenInfo := contract.TokenInfo{ -// Token: freeToken.TokenID, -// TokenType: tokenType, -// TokenValue: freeToken.TokenValue, -// OwnerDID: freeToken.DID, -// BlockID: latestBlockID, -// } -// tokenInfos = append(tokenInfos, tokenInfo) -// } - -// selfTransferContractType := &contract.ContractType{ -// Type: contract.SCRBTDirectType, -// PledgeMode: contract.POWPledgeMode, -// TotalRBTs: totalTokenValue, -// TransInfo: &contract.TransInfo{ -// SenderDID: ownerDID, -// ReceiverDID: ownerDID, -// Comment: "Self transfer at " + time.Now().String(), -// TransTokens: tokenInfos, -// }, -// ReqID: reqID, -// } - -// selfTransferContract := contract.CreateNewContract(selfTransferContractType) - -// err = selfTransferContract.UpdateSignature(dc) -// if err != nil { -// c.log.Error(err.Error()) -// response.Message = err.Error() -// return response -// } - -// c.log.Debug("5") -// consensusRequest := &ConensusRequest{ -// ReqID: uuid.New().String(), -// Type: 2, // TODO: need to be decided -// SenderPeerID: selfPeerId, -// ReceiverPeerID: selfPeerId, -// ContractBlock: selfTransferContract.GetBlock(), -// } - -// c.log.Debug("6") -// transactionDetails, _, err := c.initiateConsensus(consensusRequest, selfTransferContract, dc) -// if err != nil { -// c.log.Error("Consensus failed ", "err", err) -// response.Message = "Consensus failed " + err.Error() -// return response -// } -// transactionDetails.Amount = totalTokenValue -// et := time.Now() -// dif := et.Sub(st) -// transactionDetails.TotalTime = float64(dif.Milliseconds()) - -// // if err := c.w.AddTransactionHistory(transactionDetails); err != nil { -// // errMsg := fmt.Sprintf("Error occured while adding transaction details: %v", err) -// // c.log.Error(errMsg) -// // response.Message = errMsg -// // return response -// // } - -// c.log.Info("Self Transfer finished successfully", "duration", dif, " trnxid", transactionDetails.TransactionID) -// response.Status = true - -// return response -// } - -// // func getTotalValueFromTokens(tokens []wallet.Token) float64 { -// // var totatValue float64 = 0.0 - -// // for _, token := range tokens { -// // totatValue += token.TokenValue -// // } - -// // return totatValue -// // } \ No newline at end of file diff --git a/core/storage/storage.go b/core/storage/storage.go index f91d8c49..3f60c4d6 100644 --- a/core/storage/storage.go +++ b/core/storage/storage.go @@ -13,6 +13,7 @@ type Storage interface { WriteBatch(storageName string, vaule interface{}, batchSize int) error ReadWithOffset(storageName string, offset int, limit int, vaule interface{}, querryString string, querryVaule ...interface{}) error GetDataCount(stroageName string, querryString string, querryVaule ...interface{}) int64 + Drop(storageName string, value interface{}) error Close() error } diff --git a/core/storage/storage_db.go b/core/storage/storage_db.go index f78bef1e..24f2a516 100644 --- a/core/storage/storage_db.go +++ b/core/storage/storage_db.go @@ -68,3 +68,8 @@ func (s *StorageDB) Close() error { } return db.Close() } + +// Drop will remove the table from DB +func (s *StorageDB) Drop(storageName string, value interface{}) error { + return s.ad.DropTable(storageName, value) +} \ No newline at end of file diff --git a/core/unpledge.go b/core/unpledge.go index 386d0bd3..f39a52e2 100644 --- a/core/unpledge.go +++ b/core/unpledge.go @@ -1,8 +1,6 @@ package core import ( - "encoding/base64" - "encoding/json" "errors" "fmt" "strings" @@ -15,51 +13,54 @@ import ( tkn "github.com/rubixchain/rubixgoplatform/token" ) -const UnpledgeQueueTable string = "unpledgequeue" const pledgePeriodInSeconds int = 7 * 24 * 60 * 60 // Pledging period: 7 days -type TransTokenBlock struct { - TokenID string `json:"token_id"` - TransferBlock string `json:"token_block"` -} +func (c *Core) ForceUnpledgePOWBasedPledgedTokens() error { + // Load data from UnpledgeQueueInfo table + unpledgeQueueInfo, err := c.w.Migration_GetUnpledgeQueueInfo() + if err != nil { + return err + } -type PledgeUnpledgeBlock struct { - TokenID string `json:"token_id"` - PledgeBlock string `json:"pledge_block"` - UnpledgeBlock string `json:"unpledge_block"` -} + // unpledge all POW based pledged tokens + for _, info := range unpledgeQueueInfo { + pledgeToken := info.Token + pledgeTokenType, err := getTokenType(c.w, pledgeToken, c.testNet) + if err != nil { + return fmt.Errorf("failed to unpledge POW based pledge token %v, err: %v", pledgeToken, err) + } + pledgeTokenOwner, err := getTokenOwner(c.w, pledgeToken) + if err != nil { + return fmt.Errorf("failed to unpledge POW based pledge token %v, err: %v", pledgeToken, err) + } + + _, _, err = unpledgeToken(c, pledgeToken, pledgeTokenType, pledgeTokenOwner) + if err != nil { + c.log.Error("failed to unpledge POW based pledge token %v, err: %v", pledgeToken, err) + return fmt.Errorf("failed to unpledge POW based pledge token %v, err: %v", pledgeToken, err) + } + } -type PledgeInformation struct { - TokenID string `json:"token_id"` - TokenType int `json:"token_type"` - PledgeBlockID string `json:"pledge_block_id"` - UnpledgeBlockID string `json:"unpledge_block_id"` - QuorumDID string `json:"quorum_did"` - TransactionID string `json:"transaction_id"` -} + // Drop the UnpledgeSequence table + tableDropErr := c.w.Migration_DropUnpledgeQueueTable() + if tableDropErr != nil { + return tableDropErr + } -type UnpledgeQueueInfo struct { - TransactionID string `gorm:"column:tx_id;primaryKey"` - PledgeTokens string `gorm:"column:pledge_tokens"` - Epoch int64 `gorm:"column:epoch"` - QuorumDID string `gorm:"column:quorum_did"` + return nil } + func (c *Core) InititateUnpledgeProcess() error { // Get the list of transactions from the unpledgeQueue table - var UnpledgeQueueInfoList []UnpledgeQueueInfo - err := c.s.Read(UnpledgeQueueTable, &UnpledgeQueueInfoList, "tx_id != ?", "") + unpledgeSequenceInfo, err := c.w.GetUnpledgeSequenceDetails() if err != nil { - if strings.Contains(err.Error(), "no records found") { - c.log.Info("No tokens left to unpledge") - } else { - return err - } + return err } - var pledgeInformation []*PledgeInformation + var pledgeInformation []*wallet.PledgeInformation - for _, info := range UnpledgeQueueInfoList { + for _, info := range unpledgeSequenceInfo { var readyToUnpledge bool = false // Get all the token hashes by their transaction ID. @@ -84,7 +85,6 @@ func (c *Core) InititateUnpledgeProcess() error { } else { readyToUnpledge = true c.log.Debug("All tokens have undergone state chanage. Proceeding to unpledge...") - } if readyToUnpledge { @@ -94,175 +94,156 @@ func (c *Core) InititateUnpledgeProcess() error { return err } - creditStorageErr := storeCredit(c, info.TransactionID, info.QuorumDID, pledgeInformation) + + creditStorageErr := c.w.StoreCredit(info.TransactionID, info.QuorumDID, pledgeInformation) if creditStorageErr != nil { - c.log.Error(fmt.Sprintf("failed while storing credits, err: %v", creditStorageErr.Error())) - return err + errMsg := fmt.Errorf("failed while storing credits, err: %v", creditStorageErr.Error()) + c.log.Error(errMsg.Error()) + return errMsg } - c.s.Delete(UnpledgeQueueTable, &UnpledgeQueueInfo{}, "tx_id = ?", info.TransactionID) - c.log.Info(fmt.Sprintf("Unpledging for tx %v are successful. Credits have been awarded", info.TransactionID)) + removeUnpledgeSequenceInfoErr := c.w.RemoveUnpledgeSequenceInfo(info.TransactionID) + if removeUnpledgeSequenceInfoErr != nil { + errMsg := fmt.Errorf("failed to remove unpledgeSequenceInfo record for transaction: %v, error: %v", info.TransactionID, removeUnpledgeSequenceInfoErr) + c.log.Error(errMsg.Error()) + + // Remove the corresponding stored credit + creditRemovalErr := c.w.RemoveCredit(info.TransactionID) + if creditRemovalErr != nil { + errMsg := fmt.Errorf("failed to remove credit for transaction ID: %v", creditRemovalErr) + c.log.Error(errMsg.Error()) + return errMsg + } + + return errMsg + } + c.log.Info(fmt.Sprintf("Unpledging for transaction %v was successful. Credits have been awarded", info.TransactionID)) } } return nil } -func storeCredit(c *Core, txID string, quorumDID string, pledgeInfo []*PledgeInformation) error { - pledgeInfoBytes, err := json.Marshal(pledgeInfo) - if err != nil { - return fmt.Errorf("failed while marshalling credits: %v", err.Error()) +func unpledgeToken(c *Core, pledgeToken string, pledgeTokenType int, quorumDID string) (pledgeID string, unpledgeId string, err error) { + b := c.w.GetLatestTokenBlock(pledgeToken, pledgeTokenType) + if b == nil { + c.log.Error("Failed to unpledge invalid tokne chain block for token ", pledgeToken, " having token type as ", pledgeTokenType) + return "", "", fmt.Errorf("failed to unpledge invalid tokne chain block for token ", pledgeToken, " having token type as ", pledgeTokenType) } - pledgeInfoEncoded := base64.StdEncoding.EncodeToString(pledgeInfoBytes) - credit := &wallet.Credit{ - DID: quorumDID, - Credit: pledgeInfoEncoded, - Tx: txID, + if b.GetTransType() != block.TokenPledgedType { + c.log.Error(fmt.Sprintf("failed while unpledging token %v, token must be in pledged state before unpledging", pledgeToken)) + return "", "", fmt.Errorf("failed while unpledging token %v, token must be in pledged state before unpledging", pledgeToken) } - return c.s.Write(wallet.CreditStorage, credit) -} - -func unpledgeAllTokens(c *Core, transactionID string, pledgeTokens string, quorumDID string) ([]*PledgeInformation, error) { - c.log.Debug(fmt.Sprintf("Executing Callback for tx for unpledging: %v", transactionID)) - - var pledgeInfoList []*PledgeInformation = make([]*PledgeInformation, 0) - pledgeTokensList := strings.Split(pledgeTokens, ",") - - if len(pledgeTokensList) == 0 { - return nil, fmt.Errorf("expected atleast one pledged token for unpledging") + pledgeID, err = b.GetBlockID(pledgeToken) + if err != nil { + errMsg := fmt.Sprintf("failed while unpledging token %v, unable to fetch block ID", pledgeToken) + c.log.Error(errMsg) + return "", "", errors.New(errMsg) } - for _, pledgeToken := range pledgeTokensList { - var tokenValue float64 - var tokenType int - - // Read Token from token hash - walletToken, err := c.w.ReadToken(pledgeToken) - if err != nil { - return nil, err - } - tokenValue = walletToken.TokenValue - - c.log.Debug(fmt.Sprintf("Tx: %v, Status of pledge token %v is %v", transactionID, pledgeToken, walletToken.TokenStatus)) + ctcb := make(map[string]*block.Block) + tsb := make([]block.TransTokens, 0) - if c.testNet { - if tokenValue == 1 { - tokenType = tkn.TestTokenType - } else if tokenValue < 1 { - tokenType = tkn.TestPartTokenType - } - } else { - if tokenValue == 1 { - tokenType = tkn.RBTTokenType - } else if tokenValue < 1 { - tokenType = tkn.PartTokenType - } - } + ts := block.TransTokens{ + Token: pledgeToken, + TokenType: pledgeTokenType, + } - b := c.w.GetLatestTokenBlock(pledgeToken, tokenType) - if b == nil { - c.log.Error("Failed to unpledge invalid tokne chain block for token ", pledgeToken, " having token type as ", tokenType) - return nil, fmt.Errorf("Failed to unpledge invalid tokne chain block for token ", pledgeToken, " having token type as ", tokenType) - } + dc, ok := c.qc[quorumDID] + if !ok { + c.log.Error("Failed to get quorum did crypto") + return "", "", fmt.Errorf("failed to get quorum did crypto") + } + tsb = append(tsb, ts) + ctcb[pledgeToken] = b + currentTime := time.Now() + + tcb := block.TokenChainBlock{ + TransactionType: block.TokenUnpledgedType, + TokenOwner: quorumDID, + TransInfo: &block.TransInfo{ + Comment: "Token is un pledged at " + currentTime.String(), + Tokens: tsb, + }, + Epoch: int(currentTime.Unix()), + } - if b.GetTransType() != block.TokenPledgedType { - c.log.Error(fmt.Sprintf("failed while unpledging token %v, token must be in pledged state before unpledging", pledgeToken)) - return nil, fmt.Errorf("failed while unpledging token %v, token must be in pledged state before unpledging", pledgeToken) - } + nb := block.CreateNewBlock(ctcb, &tcb) + if nb == nil { + c.log.Error("Failed to create new token chain block") + return "", "", fmt.Errorf("failed to create new token chain block") + } - pledgeTokenBlockID, err := b.GetBlockID(pledgeToken) - if err != nil { - errMsg := fmt.Sprintf("failed while unpledging token %v, unable to fetch block ID", pledgeToken) - c.log.Error(errMsg) - return nil, errors.New(errMsg) - } + err = nb.UpdateSignature(dc) + if err != nil { + c.log.Error("Failed to update the signature", "err", err) + return "", "", fmt.Errorf("failed to update the signature") + } - ctcb := make(map[string]*block.Block) - tsb := make([]block.TransTokens, 0) + err = c.w.CreateTokenBlock(nb) + if err != nil { + c.log.Error("Failed to update token chain block", "err", err) + return "", "", err + } - ts := block.TransTokens{ - Token: pledgeToken, - TokenType: tokenType, - } + err = c.w.UnpledgeWholeToken(quorumDID, pledgeToken, pledgeTokenType) + if err != nil { + c.log.Error("Failed to update un pledge token", "err", err) + return "", "", err + } - dc, ok := c.qc[quorumDID] - if !ok { - c.log.Error("Failed to get quorum did crypto") - return nil, fmt.Errorf("failed to get quorum did crypto") - } - tsb = append(tsb, ts) - ctcb[pledgeToken] = b - currentTime := time.Now() - - tcb := block.TokenChainBlock{ - TransactionType: block.TokenUnpledgedType, - TokenOwner: quorumDID, - TransInfo: &block.TransInfo{ - Comment: "Token is un pledged at " + currentTime.String(), - Tokens: tsb, - }, - Epoch: int(currentTime.Unix()), - } + unpledgeId, err = nb.GetBlockID(pledgeToken) + if err != nil { + errMsg := fmt.Sprintf("failed while unpledging token %v, unable to fetch block ID", pledgeToken) + c.log.Error(errMsg) + return "", "", errors.New(errMsg) + } - nb := block.CreateNewBlock(ctcb, &tcb) - if nb == nil { - c.log.Error("Failed to create new token chain block") - return nil, fmt.Errorf("failed to create new token chain block") - } + return +} - err = nb.UpdateSignature(dc) - if err != nil { - c.log.Error("Failed to update the signature", "err", err) - return nil, fmt.Errorf("failed to update the signature") - } +func getTokenType(w *wallet.Wallet, tokenHash string, isTestnet bool) (int, error) { + var tokenType int = -1 + + walletToken, err := w.ReadToken(tokenHash) + if err != nil { + return tokenType, err + } - err = c.w.CreateTokenBlock(nb) - if err != nil { - c.log.Error("Failed to update token chain block", "err", err) - return nil, err + if isTestnet { + if walletToken.TokenValue == 1 { + tokenType = tkn.TestTokenType + } else if walletToken.TokenValue < 1 { + tokenType = tkn.TestPartTokenType } - - err = c.w.UnpledgeWholeToken(quorumDID, pledgeToken, tokenType) - if err != nil { - c.log.Error("Failed to update un pledge token", "err", err) - return nil, err + } else { + if walletToken.TokenValue == 1 { + tokenType = tkn.RBTTokenType + } else if walletToken.TokenValue < 1 { + tokenType = tkn.PartTokenType } + } - unpledgeTokenBlockID, err := nb.GetBlockID(pledgeToken) - if err != nil { - errMsg := fmt.Sprintf("failed while unpledging token %v, unable to fetch block ID", pledgeToken) - c.log.Error(errMsg) - return nil, errors.New(errMsg) - } + return tokenType, nil +} - // Add pledge and unpledge block information of a Pledged token - pledgeInfoList = append(pledgeInfoList, &PledgeInformation{ - TokenID: pledgeToken, - TokenType: tokenType, - PledgeBlockID: pledgeTokenBlockID, - UnpledgeBlockID: unpledgeTokenBlockID, - QuorumDID: quorumDID, - TransactionID: transactionID, - }) - } - // If the unpledging is happening after the pledging period, we can safely remove - // the TokenStateHash table records for the input transactionID - err := c.w.RemoveTokenStateHashByTransactionID(transactionID) +func getTokenOwner(w *wallet.Wallet, tokenHash string) (string, error) { + walletToken, err := w.ReadToken(tokenHash) if err != nil { - return nil, err + return "", err } - return pledgeInfoList, nil + return walletToken.DID, nil } -// type UnpledgeCBType func(transactionID string, pledgeTokens string, quorumDID string) ([]*PledgeInformation, error) -func (c *Core) ExecuteUnpledge(transactionID string, pledgeTokens string, quorumDID string) ([]*PledgeInformation, error) { - c.log.Debug(fmt.Sprintf("Executing Callback for tx for unpledging: %v", transactionID)) - var pledgeInfoList []*PledgeInformation = make([]*PledgeInformation, 0) +func unpledgeAllTokens(c *Core, transactionID string, pledgeTokens string, quorumDID string) ([]*wallet.PledgeInformation, error) { + c.log.Debug(fmt.Sprintf("Executing Callback for tx for unpledging: %v", transactionID)) + + var pledgeInfoList []*wallet.PledgeInformation = make([]*wallet.PledgeInformation, 0) pledgeTokensList := strings.Split(pledgeTokens, ",") if len(pledgeTokensList) == 0 { @@ -270,112 +251,20 @@ func (c *Core) ExecuteUnpledge(transactionID string, pledgeTokens string, quorum } for _, pledgeToken := range pledgeTokensList { - var tokenValue float64 - var tokenType int - - // Read Token from token hash - walletToken, err := c.w.ReadToken(pledgeToken) + pledgeTokenType, err := getTokenType(c.w, pledgeToken, c.testNet) if err != nil { - return nil, err + return nil, fmt.Errorf("failed while unpledging token %v, err: %v", pledgeToken, err) } - tokenValue = walletToken.TokenValue - - c.log.Debug(fmt.Sprintf("Tx: %v, Status of pledge token %v is %v", transactionID, pledgeToken, walletToken.TokenStatus)) - if c.testNet { - if tokenValue == 1 { - tokenType = tkn.TestTokenType - } else if tokenValue < 1 { - tokenType = tkn.TestPartTokenType - } - } else { - if tokenValue == 1 { - tokenType = tkn.RBTTokenType - } else if tokenValue < 1 { - tokenType = tkn.PartTokenType - } - } - - b := c.w.GetLatestTokenBlock(pledgeToken, tokenType) - if b == nil { - c.log.Error("Failed to unpledge invalid tokne chain block for token ", pledgeToken, " having token type as ", tokenType) - return nil, fmt.Errorf("Failed to unpledge invalid tokne chain block for token ", pledgeToken, " having token type as ", tokenType) - } - - if b.GetTransType() != block.TokenPledgedType { - c.log.Error(fmt.Sprintf("failed while unpledging token %v, token must be in pledged state before unpledging", pledgeToken)) - return nil, fmt.Errorf("failed while unpledging token %v, token must be in pledged state before unpledging", pledgeToken) - } - - pledgeTokenBlockID, err := b.GetBlockID(pledgeToken) - if err != nil { - errMsg := fmt.Sprintf("failed while unpledging token %v, unable to fetch block ID", pledgeToken) - c.log.Error(errMsg) - return nil, errors.New(errMsg) - } - - ctcb := make(map[string]*block.Block) - tsb := make([]block.TransTokens, 0) - - ts := block.TransTokens{ - Token: pledgeToken, - TokenType: tokenType, - } - - dc, ok := c.qc[quorumDID] - if !ok { - c.log.Error("Failed to get quorum did crypto") - return nil, fmt.Errorf("failed to get quorum did crypto") - } - tsb = append(tsb, ts) - ctcb[pledgeToken] = b - currentTime := time.Now() - - tcb := block.TokenChainBlock{ - TransactionType: block.TokenUnpledgedType, - TokenOwner: quorumDID, - TransInfo: &block.TransInfo{ - Comment: "Token is un pledged at " + currentTime.String(), - Tokens: tsb, - }, - Epoch: int(currentTime.Unix()), - } - - nb := block.CreateNewBlock(ctcb, &tcb) - if nb == nil { - c.log.Error("Failed to create new token chain block") - return nil, fmt.Errorf("failed to create new token chain block") - } - - err = nb.UpdateSignature(dc) - if err != nil { - c.log.Error("Failed to update the signature", "err", err) - return nil, fmt.Errorf("failed to update the signature") - } - - err = c.w.CreateTokenBlock(nb) + pledgeTokenBlockID, unpledgeTokenBlockID, err := unpledgeToken(c, pledgeToken, pledgeTokenType, quorumDID) if err != nil { - c.log.Error("Failed to update token chain block", "err", err) return nil, err } - err = c.w.UnpledgeWholeToken(quorumDID, pledgeToken, tokenType) - if err != nil { - c.log.Error("Failed to update un pledge token", "err", err) - return nil, err - } - - unpledgeTokenBlockID, err := nb.GetBlockID(pledgeToken) - if err != nil { - errMsg := fmt.Sprintf("failed while unpledging token %v, unable to fetch block ID", pledgeToken) - c.log.Error(errMsg) - return nil, errors.New(errMsg) - } - // Add pledge and unpledge block information of a Pledged token - pledgeInfoList = append(pledgeInfoList, &PledgeInformation{ + pledgeInfoList = append(pledgeInfoList, &wallet.PledgeInformation{ TokenID: pledgeToken, - TokenType: tokenType, + TokenType: pledgeTokenType, PledgeBlockID: pledgeTokenBlockID, UnpledgeBlockID: unpledgeTokenBlockID, QuorumDID: quorumDID, diff --git a/core/unpledge/unpledge.go b/core/unpledge/unpledge.go deleted file mode 100644 index 63fd8134..00000000 --- a/core/unpledge/unpledge.go +++ /dev/null @@ -1,90 +0,0 @@ -package unpledge - -import ( - "github.com/rubixchain/rubixgoplatform/core/storage" - "github.com/rubixchain/rubixgoplatform/core/wallet" - - //tkn "github.com/rubixchain/rubixgoplatform/token" - "github.com/rubixchain/rubixgoplatform/wrapper/logger" -) - -const ( - UnpledgeQueueTable string = "unpledgequeue" -) - -type UnPledge struct { - s storage.Storage - testNet bool - w *wallet.Wallet - cb UnpledgeCBType - log logger.Logger -} - -type UnpledgeQueueInfo struct { - TransactionID string `gorm:"column:tx_id;primaryKey"` - PledgeTokens string `gorm:"column:pledge_tokens"` - Epoch int64 `gorm:"column:epoch"` - QuorumDID string `gorm:"column:quorum_did"` -} - -type UnpledgeCBType func(transactionID string, pledgeTokens string, quorumDID string) ([]*PledgeInformation, error) -type ReceiverOwnershipFunc func(transactionId string, receiverPeer string, receiverDID string, quorumDID string) (bool, error) - -type TransTokenBlock struct { - TokenID string `json:"token_id"` - TransferBlock string `json:"token_block"` -} - -type PledgeUnpledgeBlock struct { - TokenID string `json:"token_id"` - PledgeBlock string `json:"pledge_block"` - UnpledgeBlock string `json:"unpledge_block"` -} - -type PledgeInformation struct { - TokenID string `json:"token_id"` - TokenType int `json:"token_type"` - PledgeBlockID string `json:"pledge_block_id"` - UnpledgeBlockID string `json:"unpledge_block_id"` - QuorumDID string `json:"quorum_did"` - TransactionID string `json:"transaction_id"` -} - -func InitUnPledge(s storage.Storage, w *wallet.Wallet, testNet bool, log logger.Logger) (*UnPledge, error) { - up := &UnPledge{ - s: s, - testNet: testNet, - w: w, - log: log.Named("unpledge"), - } - err := up.s.Init(UnpledgeQueueTable, UnpledgeQueueInfo{}, true) - if err != nil { - up.log.Error("failed to init unpledge token list table", "err", err) - return nil, err - } - - return up, nil -} - -func (up *UnPledge) AddUnPledge(txId string, pledgeTokens string, epoch int64, quorumDID string) error { - var unpledgeQueueInfo UnpledgeQueueInfo - err := up.s.Read(UnpledgeQueueTable, &unpledgeQueueInfo, "tx_id = ?", txId) - if err == nil { - up.log.Error("Tokens are already in the unpledge list") - return err - } - - unpledgeQueueInfo.TransactionID = txId - unpledgeQueueInfo.PledgeTokens = pledgeTokens - unpledgeQueueInfo.Epoch = epoch - unpledgeQueueInfo.QuorumDID = quorumDID - - err = up.s.Write(UnpledgeQueueTable, &unpledgeQueueInfo) - if err != nil { - up.log.Error("Error adding tx "+txId+" to unpledge list", "err", err) - return err - } - - return nil -} - diff --git a/core/wallet/credit.go b/core/wallet/credit.go index 21589352..68d1699b 100644 --- a/core/wallet/credit.go +++ b/core/wallet/credit.go @@ -1,19 +1,42 @@ package wallet +import ( + "encoding/base64" + "encoding/json" + "fmt" +) +// TODO: Credit structure needs to be worked upon type Credit struct { DID string `gorm:"column:did"` Credit string `gorm:"column:credit;size:4000"` - Tx string `gorm:"column:tx"` + Tx string `gorm:"column:tx"` } +// TODO: Credit structure needs to be worked upon +type PledgeInformation struct { + TokenID string `json:"token_id"` + TokenType int `json:"token_type"` + PledgeBlockID string `json:"pledge_block_id"` + UnpledgeBlockID string `json:"unpledge_block_id"` + QuorumDID string `json:"quorum_did"` + TransactionID string `json:"transaction_id"` +} + +func (w *Wallet) StoreCredit(transactionID string, quorumDID string, pledgeInfo []*PledgeInformation) error { + pledgeInfoBytes, err := json.Marshal(pledgeInfo) + if err != nil { + return fmt.Errorf("failed while marshalling credits: %v", err.Error()) + } + pledgeInfoEncoded := base64.StdEncoding.EncodeToString(pledgeInfoBytes) -func (w *Wallet) StoreCredit(did string, credit string) error { - c := &Credit{ - DID: did, - Credit: credit, + credit := &Credit{ + DID: quorumDID, + Credit: pledgeInfoEncoded, + Tx: transactionID, } - return w.s.Write(CreditStorage, c) + + return w.s.Write(CreditStorage, credit) } func (w *Wallet) GetCredit(did string) ([]string, error) { @@ -29,12 +52,13 @@ func (w *Wallet) GetCredit(did string) ([]string, error) { return str, nil } -func (w *Wallet) RemoveCredit(did string, credit []string) error { - for _, c := range credit { - err := w.s.Delete(CreditStorage, &c, "did=? AND credit=?", did, c) - if err != nil { - return err - } +func (w *Wallet) RemoveCredit(transactionID string) error { + err := w.s.Delete(CreditStorage, &Credit{}, "tx = ?", transactionID) + if err != nil { + errMsg := fmt.Errorf("failed to remove Credit for transaction: %v", transactionID) + w.log.Error(errMsg.Error()) + return errMsg } + return nil } diff --git a/core/wallet/unpledge.go b/core/wallet/unpledge.go new file mode 100644 index 00000000..913aac3a --- /dev/null +++ b/core/wallet/unpledge.go @@ -0,0 +1,98 @@ +package wallet + +import ( + "fmt" + "strings" +) + +// Unpledging info associated with PoW Pledging +type migration_UnpledgeQueueInfo struct { + Token string `gorm:"column:token"` +} + +// Unpledging info associated with Periodic Pledging +type UnpledgeSequenceInfo struct { + TransactionID string `gorm:"column:tx_id;primaryKey"` + PledgeTokens string `gorm:"column:pledge_tokens"` + Epoch int64 `gorm:"column:epoch"` + QuorumDID string `gorm:"column:quorum_did"` +} + +// Methods specific to Periodic Pledging + +func (w *Wallet) GetUnpledgeSequenceDetails() ([]*UnpledgeSequenceInfo, error) { + var unpledgeSequenceDetails []*UnpledgeSequenceInfo + err := w.s.Read(UnpledgeSequence, &unpledgeSequenceDetails, "tx_id = ?", "") + if err != nil { + if strings.Contains(err.Error(), "no records found") { + return []*UnpledgeSequenceInfo{}, nil + } else { + w.log.Error("Failed to get token states", "err", err) + return nil, err + } + } + return unpledgeSequenceDetails, nil +} + +func (w *Wallet) GetUnpledgeSequenceInfoByTransactionID(transactionID string) (*UnpledgeSequenceInfo, error) { + var unpledgeSequenceInfo *UnpledgeSequenceInfo + err := w.s.Read(UnpledgeSequence, &unpledgeSequenceInfo, "tx_id = ?", transactionID) + if err != nil { + return nil, err + } + return unpledgeSequenceInfo, nil +} + +func (w *Wallet) AddUnpledgeSequenceInfo(unpledgeSequenceInfo *UnpledgeSequenceInfo) error { + err := w.s.Write(UnpledgeSequence, &unpledgeSequenceInfo) + if err != nil { + errMsg := fmt.Errorf("error while adding unpledging sequence info for transaction: %v, err: %v", unpledgeSequenceInfo.TransactionID, err) + w.log.Error(errMsg.Error()) + return err + } + + return nil +} + +func (w *Wallet) RemoveUnpledgeSequenceInfo(transactionID string) error { + err := w.s.Delete(UnpledgeSequence, &UnpledgeSequenceInfo{}, "tx_id = ?", transactionID) + if err != nil { + errMsg := fmt.Errorf("error while removing unpledging sequence info for transaction: %v, err: %v", transactionID, err) + w.log.Error(errMsg.Error()) + return err + } + + return nil +} + +// Methods specific to migration from PoW based pledging +func (w *Wallet) Migration_GetUnpledgeQueueInfo() ([]migration_UnpledgeQueueInfo, error) { + var unpledgeQueueInfo []migration_UnpledgeQueueInfo + + err := w.s.Read(UnpledgeQueueTable, &unpledgeQueueInfo, "token != ?", "") + if err != nil { + if !strings.Contains(err.Error(), "no records found") { + if strings.Contains(err.Error(), "no such table") { + w.log.Info("no PoW based pledged tokens left to unpledge") + return nil, nil + } else { + errMsg := fmt.Errorf("unable to read to pledge tokens from unpledgequeue table: %v", err) + w.log.Error(errMsg.Error()) + return nil, errMsg + } + } + } + + return unpledgeQueueInfo, nil +} + +func (w *Wallet) Migration_DropUnpledgeQueueTable() error { + err := w.s.Drop(UnpledgeQueueTable, &migration_UnpledgeQueueInfo{}) + if err != nil { + errMsg := fmt.Errorf("failed to drop the unpledgequeue table: %v", err.Error()) + w.log.Error(errMsg.Error()) + return errMsg + } + + return nil +} diff --git a/core/wallet/wallet.go b/core/wallet/wallet.go index f1db89e1..0dee3c99 100644 --- a/core/wallet/wallet.go +++ b/core/wallet/wallet.go @@ -29,6 +29,8 @@ const ( SmartContractStorage string = "smartcontract" CallBackUrlStorage string = "callbackurl" TokenStateHash string = "TokenStateHashTable" + UnpledgeQueueTable string = "unpledgequeue" + UnpledgeSequence string = "UnpledgeSequence" ) type WalletConfig struct { @@ -137,6 +139,11 @@ func InitWallet(s storage.Storage, dir string, log logger.Logger) (*Wallet, erro w.log.Error("Failed to initialize Smart Contract storage", "err", err) return nil, err } + err = w.s.Init(UnpledgeSequence, &UnpledgeSequenceInfo{}, true) + if err != nil { + w.log.Error("failed to init UnpledgeSequence table", "err", err) + return nil, err + } smartcontracTokenchainstorageDB, err := leveldb.OpenFile(dir+SmartContractTokenChainStorage, op) if err != nil { diff --git a/docs/docs.go b/docs/docs.go index 5f24031b..c9dfb017 100644 --- a/docs/docs.go +++ b/docs/docs.go @@ -807,7 +807,7 @@ const docTemplate = `{ }, "/api/run-unpledge": { "post": { - "description": "This API will initiate self RBT transfer for a specific DID", + "description": "This API will unpledge all Pledged RBT tokens", "consumes": [ "application/json" ], @@ -920,6 +920,30 @@ const docTemplate = `{ } } } + }, + "/api/unpledge-pow-unpledge-tokens": { + "post": { + "description": "This API will unpledge all PoW based pledge tokens and drop the unpledgequeue table", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "Account" + ], + "summary": "Unpledge POW Based pledge Tokens", + "operationId": "unpledge-pow-unpledge-tokens", + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/model.BasicResponse" + } + } + } + } } }, "definitions": { diff --git a/docs/swagger.json b/docs/swagger.json index 341104de..28a44c64 100644 --- a/docs/swagger.json +++ b/docs/swagger.json @@ -799,7 +799,7 @@ }, "/api/run-unpledge": { "post": { - "description": "This API will initiate self RBT transfer for a specific DID", + "description": "This API will unpledge all Pledged RBT tokens", "consumes": [ "application/json" ], @@ -912,6 +912,30 @@ } } } + }, + "/api/unpledge-pow-unpledge-tokens": { + "post": { + "description": "This API will unpledge all PoW based pledge tokens and drop the unpledgequeue table", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "Account" + ], + "summary": "Unpledge POW Based pledge Tokens", + "operationId": "unpledge-pow-unpledge-tokens", + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/model.BasicResponse" + } + } + } + } } }, "definitions": { diff --git a/docs/swagger.yaml b/docs/swagger.yaml index 82e29b4a..07e77ffc 100644 --- a/docs/swagger.yaml +++ b/docs/swagger.yaml @@ -700,7 +700,7 @@ paths: post: consumes: - application/json - description: This API will initiate self RBT transfer for a specific DID + description: This API will unpledge all Pledged RBT tokens operationId: run-unpledge produces: - application/json @@ -773,6 +773,23 @@ paths: summary: Subscribe to Smart Contract tags: - Smart Contract + /api/unpledge-pow-unpledge-tokens: + post: + consumes: + - application/json + description: This API will unpledge all PoW based pledge tokens and drop the + unpledgequeue table + operationId: unpledge-pow-unpledge-tokens + produces: + - application/json + responses: + "200": + description: OK + schema: + $ref: '#/definitions/model.BasicResponse' + summary: Unpledge POW Based pledge Tokens + tags: + - Account securityDefinitions: SessionToken: in: header diff --git a/server/server.go b/server/server.go index e4e7da59..22aa672f 100644 --- a/server/server.go +++ b/server/server.go @@ -165,6 +165,7 @@ func (s *Server) RegisterRoutes() { s.AddRoute(setup.APICheckPinnedState, "DELETE", s.AuthHandle(s.APICheckPinnedState, false, s.AuthError, true)) s.AddRoute(setup.APISelfTransfer, "POST", s.AuthHandle(s.SelfTransferHandle, false, s.AuthError, true)) s.AddRoute(setup.APIRunUnpledge, "POST", s.AuthHandle(s.RunUnpledgeHandle, false, s.AuthError, true)) + s.AddRoute(setup.APIUnpledgePOWPledgeTokens, "POST", s.AuthHandle(s.UnpledgePoWBasedPledgedTokens, false, s.AuthError, true)) } func (s *Server) ExitFunc() error { diff --git a/server/unpledge.go b/server/unpledge.go index 3fac238e..f382a9f8 100644 --- a/server/unpledge.go +++ b/server/unpledge.go @@ -10,7 +10,7 @@ import ( ) // @Summary Run Unpledge -// @Description This API will initiate self RBT transfer for a specific DID +// @Description This API will unpledge all Pledged RBT tokens // @Tags Account // @ID run-unpledge // @Accept json @@ -33,3 +33,27 @@ func (s *Server) RunUnpledgeHandle(req *ensweb.Request) *ensweb.Result { resp.Message = "Unpledging of pledged tokens is successful" return s.RenderJSON(req, resp, http.StatusOK) } + +// @Summary Unpledge POW Based pledge Tokens +// @Description This API will unpledge all PoW based pledge tokens and drop the unpledgequeue table +// @Tags Account +// @ID unpledge-pow-unpledge-tokens +// @Accept json +// @Produce json +// @Success 200 {object} model.BasicResponse +// @Router /api/unpledge-pow-unpledge-tokens [post] +func (s *Server) UnpledgePoWBasedPledgedTokens(req *ensweb.Request) *ensweb.Result { + var resp model.BasicResponse + + err := s.c.ForceUnpledgePOWBasedPledgedTokens() + if err != nil { + resp.Status = false + resp.Message = err.Error() + + return s.BasicResponse(req, false, err.Error(), nil) + } + + resp.Status = true + resp.Message = "Unpledging of all PoW based pledged tokens is successful" + return s.RenderJSON(req, resp, http.StatusOK) +} diff --git a/setup/setup.go b/setup/setup.go index 1b586879..408b08c7 100644 --- a/setup/setup.go +++ b/setup/setup.go @@ -72,6 +72,7 @@ const ( APICheckPinnedState string = "/api/check-pinned-state" APISelfTransfer string = "/api/initiate-self-transfer" APIRunUnpledge string = "/api/run-unpledge" + APIUnpledgePOWPledgeTokens string = "/api/unpledge-pow-unpledge-tokens" ) // jwt.RegisteredClaims From f404a07ccd2867c06d5efa6ce0446df5597d54b2 Mon Sep 17 00:00:00 2001 From: Arnab Ghose Date: Mon, 22 Jul 2024 15:11:41 +0530 Subject: [PATCH 101/129] fixed the query string for GetUnpledegeSequenceDetails func --- command/unpledge.go | 3 +++ core/uitl.go | 17 +++++++++++++++++ core/unpledge.go | 35 +++++++++++++++++++++++++---------- core/wallet/unpledge.go | 3 +-- server/unpledge.go | 4 ++-- 5 files changed, 48 insertions(+), 14 deletions(-) diff --git a/command/unpledge.go b/command/unpledge.go index 2880b160..f4e916fc 100644 --- a/command/unpledge.go +++ b/command/unpledge.go @@ -2,7 +2,9 @@ package command func (cmd *Command) RunUnpledge() { msg, status := cmd.c.RunUnpledge() + cmd.log.Info("Unpledging of pledged tokens has started") if !status { + cmd.log.Error(msg) return } @@ -11,6 +13,7 @@ func (cmd *Command) RunUnpledge() { } func (cmd *Command) UnpledgePOWBasedPledgedTokens() { + cmd.log.Info("Unpledging of POW-based pledged tokens has started") msg, status := cmd.c.UnpledgePOWBasedPledgedTokens() if !status { cmd.log.Error(msg) diff --git a/core/uitl.go b/core/uitl.go index bd0f5b3d..60244dfd 100644 --- a/core/uitl.go +++ b/core/uitl.go @@ -1,6 +1,8 @@ package core import ( + "fmt" + "github.com/rubixchain/rubixgoplatform/rac" "github.com/rubixchain/rubixgoplatform/token" ) @@ -13,6 +15,21 @@ const ( SmartContractString string = "sc" ) +func (c *Core) getTotalAmountFromTokenHashes(tokenHashes []string) (float64, error) { + var totalAmount float64 = 0.0 + + for _, tokenHash := range tokenHashes { + walletToken, err := c.w.ReadToken(tokenHash) + if err != nil { + return 0.0, fmt.Errorf("getTotalAmountFromTokenHashes: failed to read token %v, err: %v", tokenHash, err) + } + + totalAmount += walletToken.TokenValue + } + + return totalAmount, nil +} + func (c *Core) RACPartTokenType() int { if c.testNet { return rac.RacTestPartTokenType diff --git a/core/unpledge.go b/core/unpledge.go index f39a52e2..e32d53be 100644 --- a/core/unpledge.go +++ b/core/unpledge.go @@ -13,7 +13,7 @@ import ( tkn "github.com/rubixchain/rubixgoplatform/token" ) -const pledgePeriodInSeconds int = 7 * 24 * 60 * 60 // Pledging period: 7 days +const pledgePeriodInSeconds int = 60 // Pledging period: 7 days func (c *Core) ForceUnpledgePOWBasedPledgedTokens() error { // Load data from UnpledgeQueueInfo table @@ -51,11 +51,19 @@ func (c *Core) ForceUnpledgePOWBasedPledgedTokens() error { } -func (c *Core) InititateUnpledgeProcess() error { + + +func (c *Core) InititateUnpledgeProcess() (string, error) { + c.log.Info("Unpledging process has started...") + var totalUnpledgeAmount float64 = 0.0 + // Get the list of transactions from the unpledgeQueue table unpledgeSequenceInfo, err := c.w.GetUnpledgeSequenceDetails() if err != nil { - return err + return "", err + } + if len(unpledgeSequenceInfo) == 0 { + return "No tokens present to unpledge", nil } var pledgeInformation []*wallet.PledgeInformation @@ -69,7 +77,7 @@ func (c *Core) InititateUnpledgeProcess() error { tokenStateHashDetails, err := c.w.GetTokenStateHashByTransactionID(info.TransactionID) if err != nil { c.log.Error(fmt.Sprintf("error occured while fetching token state hashes for transaction ID: %v", info.TransactionID)) - return err + return "", err } // Not all tokens have undergone state change @@ -91,7 +99,7 @@ func (c *Core) InititateUnpledgeProcess() error { pledgeInformation, err = unpledgeAllTokens(c, info.TransactionID, info.PledgeTokens, info.QuorumDID) if err != nil { c.log.Error(fmt.Sprintf("failed while unpledging tokens for transaction: %v", info.TransactionID)) - return err + return "", err } @@ -99,7 +107,7 @@ func (c *Core) InititateUnpledgeProcess() error { if creditStorageErr != nil { errMsg := fmt.Errorf("failed while storing credits, err: %v", creditStorageErr.Error()) c.log.Error(errMsg.Error()) - return errMsg + return "", errMsg } removeUnpledgeSequenceInfoErr := c.w.RemoveUnpledgeSequenceInfo(info.TransactionID) @@ -112,16 +120,23 @@ func (c *Core) InititateUnpledgeProcess() error { if creditRemovalErr != nil { errMsg := fmt.Errorf("failed to remove credit for transaction ID: %v", creditRemovalErr) c.log.Error(errMsg.Error()) - return errMsg + return "", errMsg } - return errMsg + return "", errMsg } - c.log.Info(fmt.Sprintf("Unpledging for transaction %v was successful. Credits have been awarded", info.TransactionID)) + + unpledgeAmountForTransaction, err := c.getTotalAmountFromTokenHashes(strings.Split(info.PledgeTokens, ",")) + if err != nil { + return "", fmt.Errorf("failed while getting total pledge amount for transaction id: %v, err: %v", info.TransactionID, err) + } + + totalUnpledgeAmount += unpledgeAmountForTransaction + c.log.Info(fmt.Sprintf("Unpledging for transaction %v was successful and credits have been awarded. Total Unpledge Amount: %v RBT", info.TransactionID, unpledgeAmountForTransaction)) } } - return nil + return fmt.Sprintf("Unpledging of pledged tokens was successful, Total Unpledge Amount: %v RBT", totalUnpledgeAmount), nil } func unpledgeToken(c *Core, pledgeToken string, pledgeTokenType int, quorumDID string) (pledgeID string, unpledgeId string, err error) { diff --git a/core/wallet/unpledge.go b/core/wallet/unpledge.go index 913aac3a..6dd4665d 100644 --- a/core/wallet/unpledge.go +++ b/core/wallet/unpledge.go @@ -19,10 +19,9 @@ type UnpledgeSequenceInfo struct { } // Methods specific to Periodic Pledging - func (w *Wallet) GetUnpledgeSequenceDetails() ([]*UnpledgeSequenceInfo, error) { var unpledgeSequenceDetails []*UnpledgeSequenceInfo - err := w.s.Read(UnpledgeSequence, &unpledgeSequenceDetails, "tx_id = ?", "") + err := w.s.Read(UnpledgeSequence, &unpledgeSequenceDetails, "tx_id != ?", "") if err != nil { if strings.Contains(err.Error(), "no records found") { return []*UnpledgeSequenceInfo{}, nil diff --git a/server/unpledge.go b/server/unpledge.go index f382a9f8..921069fb 100644 --- a/server/unpledge.go +++ b/server/unpledge.go @@ -20,7 +20,7 @@ import ( func (s *Server) RunUnpledgeHandle(req *ensweb.Request) *ensweb.Result { var resp model.BasicResponse - err := s.c.InititateUnpledgeProcess() + msg, err := s.c.InititateUnpledgeProcess() if err != nil { errMsg := fmt.Sprintf("%v: %v", setup.APIRunUnpledge, err.Error()) resp.Status = false @@ -30,7 +30,7 @@ func (s *Server) RunUnpledgeHandle(req *ensweb.Request) *ensweb.Result { } resp.Status = true - resp.Message = "Unpledging of pledged tokens is successful" + resp.Message = msg return s.RenderJSON(req, resp, http.StatusOK) } From 82763c105490f5355b343fec61440d83694dbefb Mon Sep 17 00:00:00 2001 From: Arnab Ghose Date: Mon, 22 Jul 2024 17:18:20 +0530 Subject: [PATCH 102/129] fixed pledging period --- core/unpledge.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/unpledge.go b/core/unpledge.go index e32d53be..db44514d 100644 --- a/core/unpledge.go +++ b/core/unpledge.go @@ -13,7 +13,7 @@ import ( tkn "github.com/rubixchain/rubixgoplatform/token" ) -const pledgePeriodInSeconds int = 60 // Pledging period: 7 days +const pledgePeriodInSeconds int = 7 * 24 * 60 * 60 // Pledging period: 7 days func (c *Core) ForceUnpledgePOWBasedPledgedTokens() error { // Load data from UnpledgeQueueInfo table From 3fc32446bddb12babf38b2b100a6125d0b5b77f7 Mon Sep 17 00:00:00 2001 From: Allen Iype P Cherian Date: Wed, 21 Feb 2024 16:19:49 +0530 Subject: [PATCH 103/129] Add Feature : Pinning as a service --- client/transfer.go | 10 +++ command/command.go | 6 ++ command/transfer.go | 30 +++++++- contract/contract.go | 4 + contract/transaction.go | 49 ++++++++---- core/model/tokens.go | 9 +++ core/quorum_initiator.go | 128 ++++++++++++++++++++++++++++--- core/quorum_recv.go | 16 ++-- core/quorum_validation.go | 9 +++ core/transfer.go | 147 ++++++++++++++++++++++++++++++++++++ core/wallet/ipfs_service.go | 1 + core/wallet/token.go | 86 ++++++++++++++------- server/tokens.go | 19 +++++ setup/setup.go | 1 + 14 files changed, 453 insertions(+), 62 deletions(-) diff --git a/client/transfer.go b/client/transfer.go index 0449bb54..57e5e87d 100644 --- a/client/transfer.go +++ b/client/transfer.go @@ -26,3 +26,13 @@ func (c *Client) SelfTransferRBT(rt *model.RBTTransferRequest) (*model.BasicResp } return &br, nil } + +func (c *Client) PinRBT(rt *model.RBTPinRequest) (*model.BasicResponse, error) { + var br model.BasicResponse + err := c.sendJSONRequest("POST", setup.APIInitiatePinRBT, nil, rt, &br, time.Minute*2) + if err != nil { + c.log.Error("Failed to Pin RBT as a service", "err", err) + return nil, err + } + return &br, nil +} diff --git a/command/command.go b/command/command.go index 72dc1aa4..e0490efa 100644 --- a/command/command.go +++ b/command/command.go @@ -88,6 +88,7 @@ const ( SelfTransferRBT string = "self-transfer-rbt" RunUnpledge string = "run-unpledge" UnpledgePOWPledgeTokens string = "unpledge-pow-pledge-tokens" + PinRBTCmd string = "pinrbt" ) var commands = []string{VersionCmd, @@ -137,6 +138,7 @@ var commands = []string{VersionCmd, SelfTransferRBT, RunUnpledge, UnpledgePOWPledgeTokens, + PinRBTCmd, } var commandsHelp = []string{"To get tool version", @@ -265,6 +267,7 @@ type Command struct { mnemonicFile string ChildPath int TokenState string + pinningAddress string } func showVersion() { @@ -462,6 +465,7 @@ func Run(args []string) { flag.StringVar(&cmd.quorumAddr, "quorumAddr", "", "Quorum Node Address to check the status of the Quorum") flag.StringVar(&links, "links", "", "Explorer url") flag.StringVar(&cmd.TokenState, "tokenstatehash", "", "Give Token State Hash to check state") + flag.StringVar(&cmd.pinningAddress, "pinningAddress", "", "Pinning address") if len(os.Args) < 2 { fmt.Println("Invalid Command") @@ -631,6 +635,8 @@ func Run(args []string) { cmd.RunUnpledge() case UnpledgePOWPledgeTokens: cmd.UnpledgePOWBasedPledgedTokens() + case PinRBTCmd: + cmd.PinRBT() default: cmd.log.Error("Invalid command") } diff --git a/command/transfer.go b/command/transfer.go index 6e689da1..ae534923 100644 --- a/command/transfer.go +++ b/command/transfer.go @@ -27,12 +27,34 @@ func (cmd *Command) TransferRBT() { cmd.log.Info("RBT transfered successfully") } +func (cmd *Command) PinRBT() { + rt := model.RBTPinRequest{ + PinningNode: cmd.pinningAddress, + Sender: cmd.senderAddr, + TokenCount: cmd.rbtAmount, + Type: cmd.transType, + Comment: cmd.transComment, + } + + br, err := cmd.c.PinRBT(&rt) + if err != nil { + cmd.log.Error("Failed to Pin the Token", "err", err) + return + } + msg, status := cmd.SignatureResponse(br) + if !status { + cmd.log.Error("Failed to Pin RBT", "msg", msg) + return + } + cmd.log.Info(msg) + cmd.log.Info("RBT Pinned successfully") +} func (cmd *Command) SelfTransferRBT() { rt := model.RBTTransferRequest{ - Sender: cmd.senderAddr, - Receiver: cmd.senderAddr, - Type: cmd.transType, + Sender: cmd.senderAddr, + Receiver: cmd.senderAddr, + Type: cmd.transType, } br, err := cmd.c.TransferRBT(&rt) @@ -47,4 +69,4 @@ func (cmd *Command) SelfTransferRBT() { } cmd.log.Info(msg) cmd.log.Info("Self RBT transfer successful") -} \ No newline at end of file +} diff --git a/contract/contract.go b/contract/contract.go index ed1779d4..dfa6b1e5 100644 --- a/contract/contract.go +++ b/contract/contract.go @@ -294,6 +294,10 @@ func (c *Contract) GetComment() string { return c.getTransInfoString(TSCommentKey) } +func (c *Contract) GetPinningServiceDID() string { + return c.getTransInfoString(TSPinningDIDKey) +} + func (c *Contract) GetTransTokenInfo() []TokenInfo { tim := util.GetFromMap(c.sm, SCTransInfoKey) if tim == nil { diff --git a/contract/transaction.go b/contract/transaction.go index b43ac77b..18d7c55e 100644 --- a/contract/transaction.go +++ b/contract/transaction.go @@ -1,6 +1,10 @@ package contract -import "github.com/rubixchain/rubixgoplatform/util" +import ( + "time" + + "github.com/rubixchain/rubixgoplatform/util" +) // ----------TransInfo---------------------- // { @@ -29,6 +33,7 @@ const ( TSCommitedTokenInfoKey string = "8" TSExecutorDIDKey string = "9" TSSmartContractDataKey string = "10" + TSPinningDIDKey string = "11" ) const ( @@ -39,24 +44,33 @@ const ( ) type TokenInfo struct { - Token string `json:"token"` - TokenType int `json:"tokenType"` - TokenValue float64 `json:"tokenValue"` - OwnerDID string `json:"ownerDID"` - BlockID string `json:"blockID"` + Token string `json:"token"` + TokenType int `json:"tokenType"` + TokenValue float64 `json:"tokenValue"` + OwnerDID string `json:"ownerDID"` + PinningNodeDID string `json:"pinningNodeDID"` + BlockID string `json:"blockID"` +} + +type PinInfo struct { + PinnedFrom time.Time `json:"pinnedFrom"` + PinnedTo time.Time `json:"pinnedTo"` } type TransInfo struct { - SenderDID string `json:"senderDID"` - ReceiverDID string `json:"receiverDID"` - Comment string `json:"comment"` - TransTokens []TokenInfo `json:"TransTokens"` - ExchangeTokens []TokenInfo `json:"excahngeTokens"` - CommitedTokens []TokenInfo `json:"comitedtokens"` - DeployerDID string `json:"deployerDID` - SmartContractToken string `json:"smartcontractToken` - ExecutorDID string `json:"executorDID"` - SmartContractData string `json:"smartcontractdata"` + SenderDID string `json:"senderDID"` + ReceiverDID string `json:"receiverDID"` + PinningNodeDID string `json:"pinningNodeDID"` + Comment string `json:"comment"` + TransTokens []TokenInfo `json:"TransTokens"` + ExchangeTokens []TokenInfo `json:"excahngeTokens"` + CommitedTokens []TokenInfo `json:"comitedtokens"` + PinningServiceTokens []TokenInfo `json:"pinnedTokens"` + PinningInfo PinInfo `json:"pinningInfo"` + DeployerDID string `json:"deployerDID"` + SmartContractToken string `json:"smartcontractToken"` + ExecutorDID string `json:"executorDID"` + SmartContractData string `json:"smartcontractdata"` } func newTokenInfoBlock(ti *TokenInfo) map[string]interface{} { @@ -86,6 +100,9 @@ func newTransInfoBlock(ts *TransInfo) map[string]interface{} { if ts.ExecutorDID != "" { ntsb[TSExecutorDIDKey] = ts.ExecutorDID } + if ts.PinningNodeDID != "" { + ntsb[TSPinningDIDKey] = ts.PinningNodeDID + } if ts.SmartContractToken != "" { ntsb[TSSmartContractTokenKey] = ts.SmartContractToken } diff --git a/core/model/tokens.go b/core/model/tokens.go index 70022ec2..955c0627 100644 --- a/core/model/tokens.go +++ b/core/model/tokens.go @@ -20,6 +20,15 @@ type RBTTransferRequest struct { Password string `json:"password"` } +type RBTPinRequest struct { + PinningNode string `json:"pinningNode"` + Sender string `json:"sender"` + TokenCount float64 `json:"tokenCOunt"` + Comment string `json:"comment"` + Type int `json:"type"` + Password string `json:"password"` +} + type RBTTransferReply struct { BasicResponse Receiver string `json:"receiver"` diff --git a/core/quorum_initiator.go b/core/quorum_initiator.go index 6e3393f6..4e0f00f0 100644 --- a/core/quorum_initiator.go +++ b/core/quorum_initiator.go @@ -32,6 +32,7 @@ const ( SmartContractDeployMode SmartContractExecuteMode SelfTransferMode + PinningServiceMode ) const ( AlphaQuorumType int = iota @@ -52,6 +53,7 @@ type ConensusRequest struct { ExecuterPeerID string `json:"executor_peer_id"` TransactionID string `json:"transaction_id"` TransactionEpoch int `json:"transaction_epoch"` + PinningNodePeerID string `json:"pinning_node_peer_id"` } type ConensusReply struct { @@ -109,12 +111,13 @@ type UpdatePledgeRequest struct { } type SendTokenRequest struct { - Address string `json:"peer_id"` - TokenInfo []contract.TokenInfo `json:"token_info"` - TokenChainBlock []byte `json:"token_chain_block"` - QuorumList []string `json:"quorum_list"` - QuorumInfo []QuorumDIDPeerMap `json:"quorum_info"` + Address string `json:"peer_id"` + TokenInfo []contract.TokenInfo `json:"token_info"` + TokenChainBlock []byte `json:"token_chain_block"` + QuorumList []string `json:"quorum_list"` + QuorumInfo []QuorumDIDPeerMap `json:"quorum_info"` TransactionEpoch int `json:"transaction_epoch"` + PinningServiceMode bool `json:"pinning_service_mode"` } type PledgeReply struct { @@ -451,11 +454,12 @@ func (c *Core) initiateConsensus(cr *ConensusRequest, sc *contract.Contract, dc } defer rp.Close() sr := SendTokenRequest{ - Address: cr.SenderPeerID + "." + sc.GetSenderDID(), - TokenInfo: ti, - TokenChainBlock: nb.GetBlock(), - QuorumList: cr.QuorumList, + Address: cr.SenderPeerID + "." + sc.GetSenderDID(), + TokenInfo: ti, + TokenChainBlock: nb.GetBlock(), + QuorumList: cr.QuorumList, TransactionEpoch: cr.TransactionEpoch, + PinningServiceMode: false, } //fetching quorums' info from PeerDIDTable to share with the receiver @@ -625,6 +629,112 @@ func (c *Core) initiateConsensus(cr *ConensusRequest, sc *contract.Contract, dc return nil, nil, err } + return &td, pl, nil + } else if cr.Mode == PinningServiceMode { + c.log.Info("Mode: PinningServiceMode ") + c.log.Debug("Pinning Node PeerId", cr.PinningNodePeerID) + c.log.Debug("Pinning Service DID", sc.GetPinningServiceDID()) + rp, err := c.getPeer(cr.PinningNodePeerID + "." + sc.GetPinningServiceDID()) + if err != nil { + c.log.Error("Pinning Node not connected", "err", err) + return nil, nil, err + } + defer rp.Close() + sr := SendTokenRequest{ + Address: cr.SenderPeerID + "." + sc.GetSenderDID(), + TokenInfo: ti, + TokenChainBlock: nb.GetBlock(), + QuorumList: cr.QuorumList, + PinningServiceMode: true, + } + var br model.BasicResponse + err = rp.SendJSONRequest("POST", APISendReceiverToken, nil, &sr, &br, true) + if err != nil { + c.log.Error("Unable to send tokens to receiver", "err", err) + return nil, nil, err + } + if !br.Status { + c.log.Error("Unable to send tokens to receiver", "msg", br.Message) + return nil, nil, fmt.Errorf("unable to send tokens to receiver, " + br.Message) + } + err = c.w.TokensTransferred(sc.GetSenderDID(), ti, nb, rp.IsLocal(), true) + if err != nil { + c.log.Error("Failed to transfer tokens", "err", err) + return nil, nil, err + } else if cr.Mode == PinningServiceMode { + c.log.Debug("Mode = PinningServiceMode ") + c.log.Debug("Pinning Node PeerId", cr.PinningNodePeerID) + c.log.Debug("Pinning Service DID", sc.GetPinningServiceDID()) + rp, err := c.getPeer(cr.PinningNodePeerID + "." + sc.GetPinningServiceDID()) + if err != nil { + c.log.Error("Pinning Node not connected", "err", err) + return nil, nil, err + } + defer rp.Close() + sr := SendTokenRequest{ + Address: cr.SenderPeerID + "." + sc.GetSenderDID(), + TokenInfo: ti, + TokenChainBlock: nb.GetBlock(), + QuorumList: cr.QuorumList, + PinningServiceMode: true, + } + var br model.BasicResponse + err = rp.SendJSONRequest("POST", APISendReceiverToken, nil, &sr, &br, true) + if err != nil { + c.log.Error("Unable to send tokens to receiver", "err", err) + return nil, nil, err + } + if !br.Status { + c.log.Error("Unable to send tokens to receiver", "msg", br.Message) + return nil, nil, fmt.Errorf("unable to send tokens to receiver, " + br.Message) + } + err = c.w.TokensTransferred(sc.GetSenderDID(), ti, nb, rp.IsLocal(), true) + if err != nil { + c.log.Error("Failed to transfer tokens", "err", err) + return nil, nil, err + } + //Commented out this unpinning part so that the unpin is not done from the sender side + // for _, t := range ti { + // c.w.UnPin(t.Token, wallet.PrevSenderRole, sc.GetSenderDID()) + // } + //call ipfs repo gc after unpinnning + // c.ipfsRepoGc() + nbid, err := nb.GetBlockID(ti[0].Token) + if err != nil { + c.log.Error("Failed to get block id", "err", err) + return nil, nil, err + } + + td := wallet.TransactionDetails{ + TransactionID: tid, + TransactionType: nb.GetTransType(), + BlockID: nbid, + Mode: wallet.SendMode, + SenderDID: sc.GetSenderDID(), + ReceiverDID: sc.GetPinningServiceDID(), + Comment: sc.GetComment(), + DateTime: time.Now(), + Status: true, + } + return &td, pl, nil + } + nbid, err := nb.GetBlockID(ti[0].Token) + if err != nil { + c.log.Error("Failed to get block id", "err", err) + return nil, nil, err + } + + td := wallet.TransactionDetails{ + TransactionID: tid, + TransactionType: nb.GetTransType(), + BlockID: nbid, + Mode: wallet.SendMode, + SenderDID: sc.GetSenderDID(), + ReceiverDID: sc.GetPinningServiceDID(), + Comment: sc.GetComment(), + DateTime: time.Now(), + Status: true, + } return &td, pl, nil case SelfTransferMode: var quorumInfo []QuorumDIDPeerMap = make([]QuorumDIDPeerMap, 0) diff --git a/core/quorum_recv.go b/core/quorum_recv.go index 186b0e8d..93f9afb6 100644 --- a/core/quorum_recv.go +++ b/core/quorum_recv.go @@ -47,9 +47,9 @@ func (c *Core) addUnpledgeDetails(req *ensweb.Request) *ensweb.Result { unpledgeSequenceInfo := &wallet.UnpledgeSequenceInfo{ TransactionID: transactionID, - PledgeTokens: pledgeTokenHashesStrArr, - Epoch: transactionEpoch, - QuorumDID: quorumDID, + PledgeTokens: pledgeTokenHashesStrArr, + Epoch: transactionEpoch, + QuorumDID: quorumDID, } err := c.w.AddUnpledgeSequenceInfo(unpledgeSequenceInfo) @@ -156,6 +156,12 @@ func (c *Core) quorumRBTConsensus(req *ensweb.Request, did string, qdc didcrypto ti := sc.GetTransTokenInfo() results := make([]MultiPinCheckRes, len(ti)) var wg sync.WaitGroup + var receiverPeerId = cr.ReceiverPeerID + if receiverPeerId == "" { + c.log.Debug("Receiver peer id is nil: checking for pinning node peer id") + receiverPeerId = cr.PinningNodePeerID + c.log.Debug("Pinning Node Peer Id", receiverPeerId) + } for i := range ti { wg.Add(1) go c.pinCheck(ti[i].Token, i, cr.SenderPeerID, cr.ReceiverPeerID, results, &wg) @@ -516,7 +522,7 @@ func (c *Core) quorumConensus(req *ensweb.Request) *ensweb.Result { return c.l.RenderJSON(req, &crep, http.StatusOK) } switch cr.Mode { - case RBTTransferMode, SelfTransferMode: + case RBTTransferMode, SelfTransferMode, PinningServiceMode: c.log.Debug("RBT consensus started") return c.quorumRBTConsensus(req, did, qdc, &cr) case DTCommitMode: @@ -741,7 +747,7 @@ func (c *Core) updateReceiverToken( c.log.Debug("Token", tokenStateCheckResult[i].Token, "Message", tokenStateCheckResult[i].Message) } - updatedTokenStateHashes, err := c.w.TokensReceived(receiverDID, tokenInfo, b, senderPeerId, receiverPeerId, c.ipfs) + updatedTokenStateHashes, err := c.w.TokensReceived(receiverDID, tokenInfo, b, senderPeerId, receiverPeerId, c.ipfs, sr.PinningServiceMode) if err != nil { return nil, fmt.Errorf("Failed to update token status, error: %v", err) } diff --git a/core/quorum_validation.go b/core/quorum_validation.go index b7717572..e4f429cd 100644 --- a/core/quorum_validation.go +++ b/core/quorum_validation.go @@ -220,6 +220,15 @@ func (c *Core) validateTokenOwnership(cr *ConensusRequest, sc *contract.Contract c.log.Error("Invalid token chain block") return false, fmt.Errorf("Invalid token chain block for ", ti[i].Token) } + c.log.Info("Validating token ownership", "token", ti[i].Token, "owner", b.GetOwner(), "sender", sc.GetSenderDID()) + for _, token := range ti { + ownerDID := token.OwnerDID + c.log.Debug("OwnerDID:", ownerDID) + if ownerDID != sc.GetSenderDID() { + c.log.Error("Invalid token owner : The token is Pinned as a service", "owner", b.GetOwner(), "The node which is trying to transfer", sc.GetSenderDID()) + return false + } + } signatureValidation, err := c.validateSigner(b, quorumDID, p) if !signatureValidation || err != nil { return false, err diff --git a/core/transfer.go b/core/transfer.go index 1f05dc57..206ad060 100644 --- a/core/transfer.go +++ b/core/transfer.go @@ -333,6 +333,153 @@ func (c *Core) initiateRBTTransfer(reqID string, req *model.RBTTransferRequest) return resp } +//Functions to initiate PinRBT + +func (c *Core) InitiatePinRBT(reqID string, req *model.RBTPinRequest) { + br := c.initiatePinRBT(reqID, req) + dc := c.GetWebReq(reqID) + if dc == nil { + c.log.Error("Failed to get did channels") + return + } + dc.OutChan <- br +} + +func (c *Core) initiatePinRBT(reqID string, req *model.RBTPinRequest) *model.BasicResponse { + st := time.Now() + resp := &model.BasicResponse{ + Status: false, + } + _, did, ok := util.ParseAddress(req.Sender) + if !ok { + resp.Message = "Invalid sender DID" + return resp + } + + pinningNodepeerid, pinningNodeDID, ok := util.ParseAddress(req.PinningNode) + if !ok { + resp.Message = "Invalid pinning DID" + return resp + } + dc, err := c.SetupDID(reqID, did) + if err != nil { + resp.Message = "Failed to setup DID, " + err.Error() + return resp + } + // Get the required tokens from the DID bank + // this method locks the token needs to be released or + // removed once it done with the transfer + wt, err := c.GetTokens(dc, did, req.TokenCount) + if err != nil { + c.log.Error("Failed to get tokens", "err", err) + resp.Message = "Insufficient tokens or tokens are locked" + return resp + } + // release the locked tokens before exit + defer c.w.ReleaseTokens(wt) + + for i := range wt { + c.w.Pin(wt[i].TokenID, wallet.PinningRole, did) //my comment : In this pin function the wallet.OwnerRole is changed to wallet.PinRole + } + p, err := c.getPeer(req.PinningNode) + if err != nil { + resp.Message = "Failed to get pinning peer, " + err.Error() + return resp + } + defer p.Close() + + wta := make([]string, 0) + for i := range wt { + wta = append(wta, wt[i].TokenID) + } + + tis := make([]contract.TokenInfo, 0) + + for i := range wt { + tts := "rbt" + if wt[i].TokenValue != 1 { + tts = "part" + } + tt := c.TokenType(tts) + blk := c.w.GetLatestTokenBlock(wt[i].TokenID, tt) + if blk == nil { + c.log.Error("failed to get latest block, invalid token chain") + resp.Message = "failed to get latest block, invalid token chain" + return resp + } + bid, err := blk.GetBlockID(wt[i].TokenID) + if err != nil { + c.log.Error("failed to get block id", "err", err) + resp.Message = "failed to get block id, " + err.Error() + return resp + } + //OwnerDID will be the same as the sender, so that ownership is not changed. + ti := contract.TokenInfo{ + Token: wt[i].TokenID, + TokenType: tt, + TokenValue: wt[i].TokenValue, + OwnerDID: did, + PinningNodeDID: wt[i].DID, + BlockID: bid, + } + + tis = append(tis, ti) + } + sct := &contract.ContractType{ + Type: contract.SCRBTDirectType, + PledgeMode: contract.POWPledgeMode, + TotalRBTs: req.TokenCount, + TransInfo: &contract.TransInfo{ + SenderDID: did, + PinningNodeDID: pinningNodeDID, + Comment: req.Comment, + TransTokens: tis, + }, + } + sc := contract.CreateNewContract(sct) + err = sc.UpdateSignature(dc) + if err != nil { + c.log.Error(err.Error()) + resp.Message = err.Error() + return resp + } + cr := &ConensusRequest{ + ReqID: uuid.New().String(), + Type: req.Type, + SenderPeerID: c.peerID, + PinningNodePeerID: pinningNodepeerid, + ContractBlock: sc.GetBlock(), + Mode: 6, + } + td, _, err := c.initiateConsensus(cr, sc, dc) + if err != nil { + c.log.Error("Consensus failed", "err", err) + resp.Message = "Consensus failed" + err.Error() + return resp + } + et := time.Now() + dif := et.Sub(st) + td.Amount = req.TokenCount + td.TotalTime = float64(dif.Milliseconds()) + c.w.AddTransactionHistory(td) + etrans := &ExplorerTrans{ + TID: td.TransactionID, + SenderDID: did, + ReceiverDID: pinningNodeDID, + Amount: req.TokenCount, + TrasnType: req.Type, + TokenIDs: wta, + QuorumList: cr.QuorumList, + TokenTime: float64(dif.Milliseconds()), + } + c.ec.ExplorerTransaction(etrans) + c.log.Info("Pinning finished successfully", "duration", dif, " trnxid", td.TransactionID) + resp.Status = true + msg := fmt.Sprintf("Pinning finished successfully in %v with trnxid %v", dif, td.TransactionID) + resp.Message = msg + return resp +} + func extractHash(input string) (string, error) { values := strings.Split(input, "-") if len(values) != 2 { diff --git a/core/wallet/ipfs_service.go b/core/wallet/ipfs_service.go index 14b8c110..3b3590d3 100644 --- a/core/wallet/ipfs_service.go +++ b/core/wallet/ipfs_service.go @@ -25,6 +25,7 @@ const ( QuorumPinRole QuorumUnpinRole ParentTokenPinByQuorumRole + PinningRole ) // modified pin method that pins token and update in DB with role of the machine pinning diff --git a/core/wallet/token.go b/core/wallet/token.go index 58bed1fe..6b9ff1a6 100644 --- a/core/wallet/token.go +++ b/core/wallet/token.go @@ -1,15 +1,15 @@ package wallet import ( + "bytes" "fmt" "os" "strings" - "bytes" + ipfsnode "github.com/ipfs/go-ipfs-api" "github.com/rubixchain/rubixgoplatform/block" "github.com/rubixchain/rubixgoplatform/contract" "github.com/rubixchain/rubixgoplatform/util" - ipfsnode "github.com/ipfs/go-ipfs-api" ) const ( @@ -28,11 +28,13 @@ const ( TokenChainSyncIssue TokenPledgeIssue TokenIsBeingDoubleSpent + TokenIsPinnedAsService ) const ( Zero int = iota One ) + const ( RACTestTokenType int = iota RACOldNFTType @@ -162,7 +164,7 @@ func (w *Wallet) GetWholeTokens(did string, num int) ([]Token, int, error) { w.l.Lock() defer w.l.Unlock() var t []Token - err := w.s.Read(TokenStorage, &t, "did=? AND token_status=? AND token_value=?", did, TokenIsFree, 1.0) + err := w.s.Read(TokenStorage, &t, "did=? AND (token_status=? OR token_status=?) AND token_value=?", did, TokenIsFree, TokenIsPinnedAsService, 1.0) if err != nil { return nil, num, err } @@ -345,7 +347,7 @@ func (w *Wallet) UpdateToken(t *Token) error { return nil } -func (w *Wallet) TokensTransferred(did string, ti []contract.TokenInfo, b *block.Block, local bool) error { +func (w *Wallet) TokensTransferred(did string, ti []contract.TokenInfo, b *block.Block, local bool, pinningServiceMode bool) error { w.l.Lock() defer w.l.Unlock() // ::TODO:: need to address part & other tokens @@ -355,15 +357,21 @@ func (w *Wallet) TokensTransferred(did string, ti []contract.TokenInfo, b *block if err != nil { return err } + var tokenStatus int + if pinningServiceMode { + tokenStatus = TokenIsPinnedAsService + } else { + tokenStatus = TokenIsTransferred + } for i := range ti { var t Token err := w.s.Read(TokenStorage, &t, "did=? AND token_id=?", did, ti[i].Token) if err != nil { return err } - t.TokenStatus = TokenIsTransferred + t.TokenStatus = tokenStatus t.TransactionID = b.GetTid() - + err = w.s.Update(TokenStorage, &t, "did=? AND token_id=?", did, ti[i].Token) if err != nil { return err @@ -394,7 +402,7 @@ func (w *Wallet) TokensTransferred(did string, ti []contract.TokenInfo, b *block return nil } -func (w *Wallet) TokensReceived(did string, ti []contract.TokenInfo, b *block.Block, senderPeerId string, receiverPeerId string, ipfsShell *ipfsnode.Shell) ([]string, error) { +func (w *Wallet) TokensReceived(did string, ti []contract.TokenInfo, b *block.Block, senderPeerId string, receiverPeerId string, pinningServiceMode bool, ipfsShell *ipfsnode.Shell) ([]string, error) { w.l.Lock() defer w.l.Unlock() // TODO :: Needs to be address @@ -419,10 +427,13 @@ func (w *Wallet) TokensReceived(did string, ti []contract.TokenInfo, b *block.Bl tokenHashMap[t] = tokenIDTokenStateHash } - for i := range ti { + // Handle each token + for _, tokenInfo := range ti { + // Check if token already exists var t Token - err := w.s.Read(TokenStorage, &t, "token_id=?", ti[i].Token) + err := w.s.Read(TokenStorage, &t, "token_id=?", tokenInfo.Token) if err != nil || t.TokenID == "" { + // Token doesn't exist, proceed to handle it dir := util.GetRandString() err := util.CreateDir(dir) if err != nil { @@ -430,50 +441,69 @@ func (w *Wallet) TokensReceived(did string, ti []contract.TokenInfo, b *block.Bl return nil, err } defer os.RemoveAll(dir) - err = w.Get(ti[i].Token, did, OwnerRole, dir) - if err != nil { - w.log.Error("Faled to get token", "err", err) + + // Get the token + if err := w.Get(tokenInfo.Token, did, OwnerRole, dir); err != nil { + w.log.Error("Failed to get token", "err", err) return nil, err } - gb := w.GetGenesisTokenBlock(ti[i].Token, ti[i].TokenType) - pt := "" + + // Get parent token details + var parentTokenID string + gb := w.GetGenesisTokenBlock(tokenInfo.Token, tokenInfo.TokenType) if gb != nil { - pt, _, _ = gb.GetParentDetials(ti[i].Token) + parentTokenID, _, _ = gb.GetParentDetials(tokenInfo.Token) } tokenId := ti[i].Token - + + // Create new token entry t = Token{ TokenID: tokenId, TokenValue: ti[i].TokenValue, ParentTokenID: pt, + TokenID: tokenInfo.Token, + TokenValue: tokenInfo.TokenValue, + ParentTokenID: parentTokenID, DID: did, } t.TokenStateHash = tokenHashMap[tokenId] - err = w.s.Write(TokenStorage, &t) - if err != nil { + if err := w.s.Write(TokenStorage, &t); err != nil { return nil, err } } + // Update token status and pin tokens + tokenStatus := TokenIsFree + role := OwnerRole + if pinningServiceMode { + tokenStatus = TokenIsPinnedAsService + role = PinningRole + } + + // Update token status t.DID = did - t.TokenStatus = TokenIsFree + t.TokenStatus = tokenStatus t.TransactionID = b.GetTid() t.TokenStateHash = tokenHashMap[t.TokenID] - err = w.s.Update(TokenStorage, &t, "token_id=?", ti[i].Token) - if err != nil { + if err := w.s.Update(TokenStorage, &t, "token_id=?", tokenInfo.Token); err != nil { return nil, err } senderAddress := senderPeerId + "." + b.GetSenderDID() receiverAddress := receiverPeerId + "." + b.GetReceiverDID() - //Pinnig the whole tokens and pat tokens - ok, err := w.Pin(ti[i].Token, OwnerRole, did, b.GetTid(), senderAddress, receiverAddress, ti[i].TokenValue) + + // Pin the token + ok, err := w.Pin(tokenInfo.Token, role, did, b.GetTid(), senderAddress, receiverAddress, ti[i].TokenValue) if err != nil { return nil, err } if !ok { - return nil, fmt.Errorf("failed to pin token") + msg := "failed to pin token" + if pinningServiceMode { + msg = "failed to pin token as Service" + } + return fmt.Errorf(msg) } } // for i := range pt { @@ -663,7 +693,7 @@ func (w *Wallet) AddTokenStateHash(did string, tokenStateHashes []string, pledge for _, tokenStateHash := range tokenStateHashes { td.DID = did td.PledgedTokens = concatenatedpledgedtokens - td.TokenStateHash = tokenStateHash + td.TokenStateHash = tokenStateHash td.TransactionID = TransactionID err := w.s.Write(TokenStateHash, &td) @@ -707,7 +737,7 @@ func (w *Wallet) RemoveTokenStateHash(tokenstatehash string) error { err := w.s.Read(TokenStateHash, &td, "token_state_hash=?", tokenstatehash) if err != nil { if strings.Contains(err.Error(), "no records found") { - return nil + return nil } else { w.log.Error("Failed to fetch token state from DB", "err", err) return err @@ -733,7 +763,7 @@ func (w *Wallet) RemoveTokenStateHashByTransactionID(transactionID string) error w.log.Error("Failed to fetch token state from DB", "err", err) return err } else { - return nil + return nil } } @@ -744,6 +774,6 @@ func (w *Wallet) RemoveTokenStateHashByTransactionID(transactionID string) error return err } } - + return nil } diff --git a/server/tokens.go b/server/tokens.go index 8c278152..3fa33ed4 100644 --- a/server/tokens.go +++ b/server/tokens.go @@ -71,6 +71,25 @@ func (s *Server) APIInitiateRBTTransfer(req *ensweb.Request) *ensweb.Result { return s.didResponse(req, req.ID) } +// function for Pinning RBT as service +func (s *Server) APIInitiatePinRBT(req *ensweb.Request) *ensweb.Result { + var rbtReq model.RBTPinRequest + err := s.ParseJSON(req, &rbtReq) + if err != nil { + return s.BasicResponse(req, false, "Invalid input", nil) + } + _, did, ok := util.ParseAddress(rbtReq.Sender) + if !ok { + return s.BasicResponse(req, false, "Invalid sender address", nil) + } + if !s.validateDIDAccess(req, did) { + return s.BasicResponse(req, false, "DID does not have an access", nil) + } + s.c.AddWebReq(req) + go s.c.InitiatePinRBT(req.ID, &rbtReq) + return s.didResponse(req, req.ID) +} + // ShowAccount godoc // @Summary Check account balance // @Description For a mentioned DID, check the account balance diff --git a/setup/setup.go b/setup/setup.go index 408b08c7..57d58bd9 100644 --- a/setup/setup.go +++ b/setup/setup.go @@ -73,6 +73,7 @@ const ( APISelfTransfer string = "/api/initiate-self-transfer" APIRunUnpledge string = "/api/run-unpledge" APIUnpledgePOWPledgeTokens string = "/api/unpledge-pow-unpledge-tokens" + APIInitiatePinRBT string = "/api/initiate-pin-rbt" ) // jwt.RegisteredClaims From 1db36df48da42c398e19a613764221d845bfc990 Mon Sep 17 00:00:00 2001 From: Allen Iype P Cherian Date: Tue, 27 Feb 2024 09:55:06 +0530 Subject: [PATCH 104/129] Add swagger [initiate-pin-rbt] --- server/server.go | 1 + server/tokens.go | 20 ++++++++++++++++++++ 2 files changed, 21 insertions(+) diff --git a/server/server.go b/server/server.go index 22aa672f..e830b815 100644 --- a/server/server.go +++ b/server/server.go @@ -166,6 +166,7 @@ func (s *Server) RegisterRoutes() { s.AddRoute(setup.APISelfTransfer, "POST", s.AuthHandle(s.SelfTransferHandle, false, s.AuthError, true)) s.AddRoute(setup.APIRunUnpledge, "POST", s.AuthHandle(s.RunUnpledgeHandle, false, s.AuthError, true)) s.AddRoute(setup.APIUnpledgePOWPledgeTokens, "POST", s.AuthHandle(s.UnpledgePoWBasedPledgedTokens, false, s.AuthError, true)) + s.AddRoute(setup.APIInitiatePinRBT, "POST", s.AuthHandle(s.APIInitiatePinRBT, true, s.AuthError, false)) } func (s *Server) ExitFunc() error { diff --git a/server/tokens.go b/server/tokens.go index 3fa33ed4..0fae3b1f 100644 --- a/server/tokens.go +++ b/server/tokens.go @@ -72,6 +72,26 @@ func (s *Server) APIInitiateRBTTransfer(req *ensweb.Request) *ensweb.Result { } // function for Pinning RBT as service + +type RBTPinRequestSwaggoInput struct { + PinningNode string `json:"pinningNode"` + Sender string `json:"sender"` + TokenCount float64 `json:"tokenCOunt"` + Comment string `json:"comment"` + Type int `json:"type"` +} + +// ShowAccount godoc +// @Summary Initiate Pin RBT +// @Description This API will pin rbt in the Pinning node on behalf of the sender +// @Tags Account +// @ID initiate-pin-rbt +// @Accept json +// @Produce json +// @Param input body RBTPinRequestSwaggoInput true "Intitate Pin RBT" +// @Success 200 {object} model.BasicResponse +// @Router /api/initiate-pin-rbt [post] + func (s *Server) APIInitiatePinRBT(req *ensweb.Request) *ensweb.Result { var rbtReq model.RBTPinRequest err := s.ParseJSON(req, &rbtReq) From b7eaceba8b7d5adb7b2cb69508d57117d477d0f2 Mon Sep 17 00:00:00 2001 From: Allen Iype P Cherian Date: Thu, 29 Feb 2024 15:52:06 +0530 Subject: [PATCH 105/129] Fix : invalid tokenchain block --- block/block.go | 4 ++ block/transaction.go | 19 +++++----- core/quorum_initiator.go | 78 ++++++++++----------------------------- core/quorum_validation.go | 1 + 4 files changed, 35 insertions(+), 67 deletions(-) diff --git a/block/block.go b/block/block.go index e01e257a..771ed5c2 100644 --- a/block/block.go +++ b/block/block.go @@ -56,6 +56,7 @@ const ( TokenDeployedType string = "09" TokenExecutedType string = "10" TokenContractCommited string = "11" + TokenPinnedAsService string = "12" ) type TokenChainBlock struct { @@ -128,12 +129,14 @@ func InitBlock(bb []byte, bm map[string]interface{}, opts ...BlockOption) *Block if b.bb == nil { err = b.blkEncode() if err != nil { + fmt.Println("failed to encode block", err.Error(), err) return nil } } if b.bm == nil { err = b.blkDecode() if err != nil { + fmt.Println("failed to decode block", err.Error(), err) return nil } } @@ -197,6 +200,7 @@ func (b *Block) blkDecode() error { var m map[string]interface{} err := cbor.Unmarshal(b.bb, &m) if err != nil { + fmt.Println("failed to decode block", err.Error(), err) return nil } si, sok := m[TCBlockContentSigKey] diff --git a/block/transaction.go b/block/transaction.go index 589179da..77ef6421 100644 --- a/block/transaction.go +++ b/block/transaction.go @@ -69,15 +69,16 @@ type TransTokens struct { } type TransInfo struct { - SenderDID string `json:"senderDID"` - ReceiverDID string `json:"receiverDID"` - Comment string `json:"comment"` - TID string `json:"tid"` - Block []byte `json:"block"` - RefID string `json:"refID"` - Tokens []TransTokens `json:"tokens"` - DeployerDID string `json:"deployerDID"` - ExecutorDID string `json:"executorDID"` + SenderDID string `json:"senderDID"` + ReceiverDID string `json:"receiverDID"` + Comment string `json:"comment"` + TID string `json:"tid"` + Block []byte `json:"block"` + RefID string `json:"refID"` + Tokens []TransTokens `json:"tokens"` + DeployerDID string `json:"deployerDID"` + ExecutorDID string `json:"executorDID"` + PinningNodeDID string `json:"pinningNodeDID"` } func newTransToken(b *Block, tt *TransTokens) map[string]interface{} { diff --git a/core/quorum_initiator.go b/core/quorum_initiator.go index 4e0f00f0..f495dc75 100644 --- a/core/quorum_initiator.go +++ b/core/quorum_initiator.go @@ -310,7 +310,7 @@ func (c *Core) initiateConsensus(cr *ConensusRequest, sc *contract.Contract, dc // TODO:: Need to correct for part tokens switch cr.Mode { - case RBTTransferMode, NFTSaleContractMode, SelfTransferMode: + case RBTTransferMode, NFTSaleContractMode, SelfTransferMode, PinningServiceMode: ti := sc.GetTransTokenInfo() for i := range ti { reqPledgeTokens = reqPledgeTokens + ti[i].TokenValue @@ -631,7 +631,7 @@ func (c *Core) initiateConsensus(cr *ConensusRequest, sc *contract.Contract, dc return &td, pl, nil } else if cr.Mode == PinningServiceMode { - c.log.Info("Mode: PinningServiceMode ") + c.log.Debug("Mode = PinningServiceMode ") c.log.Debug("Pinning Node PeerId", cr.PinningNodePeerID) c.log.Debug("Pinning Service DID", sc.GetPinningServiceDID()) rp, err := c.getPeer(cr.PinningNodePeerID + "." + sc.GetPinningServiceDID()) @@ -647,6 +647,7 @@ func (c *Core) initiateConsensus(cr *ConensusRequest, sc *contract.Contract, dc QuorumList: cr.QuorumList, PinningServiceMode: true, } + c.log.Debug("Send Token Request", sr) var br model.BasicResponse err = rp.SendJSONRequest("POST", APISendReceiverToken, nil, &sr, &br, true) if err != nil { @@ -661,63 +662,13 @@ func (c *Core) initiateConsensus(cr *ConensusRequest, sc *contract.Contract, dc if err != nil { c.log.Error("Failed to transfer tokens", "err", err) return nil, nil, err - } else if cr.Mode == PinningServiceMode { - c.log.Debug("Mode = PinningServiceMode ") - c.log.Debug("Pinning Node PeerId", cr.PinningNodePeerID) - c.log.Debug("Pinning Service DID", sc.GetPinningServiceDID()) - rp, err := c.getPeer(cr.PinningNodePeerID + "." + sc.GetPinningServiceDID()) - if err != nil { - c.log.Error("Pinning Node not connected", "err", err) - return nil, nil, err - } - defer rp.Close() - sr := SendTokenRequest{ - Address: cr.SenderPeerID + "." + sc.GetSenderDID(), - TokenInfo: ti, - TokenChainBlock: nb.GetBlock(), - QuorumList: cr.QuorumList, - PinningServiceMode: true, - } - var br model.BasicResponse - err = rp.SendJSONRequest("POST", APISendReceiverToken, nil, &sr, &br, true) - if err != nil { - c.log.Error("Unable to send tokens to receiver", "err", err) - return nil, nil, err - } - if !br.Status { - c.log.Error("Unable to send tokens to receiver", "msg", br.Message) - return nil, nil, fmt.Errorf("unable to send tokens to receiver, " + br.Message) - } - err = c.w.TokensTransferred(sc.GetSenderDID(), ti, nb, rp.IsLocal(), true) - if err != nil { - c.log.Error("Failed to transfer tokens", "err", err) - return nil, nil, err - } - //Commented out this unpinning part so that the unpin is not done from the sender side - // for _, t := range ti { - // c.w.UnPin(t.Token, wallet.PrevSenderRole, sc.GetSenderDID()) - // } - //call ipfs repo gc after unpinnning - // c.ipfsRepoGc() - nbid, err := nb.GetBlockID(ti[0].Token) - if err != nil { - c.log.Error("Failed to get block id", "err", err) - return nil, nil, err - } - - td := wallet.TransactionDetails{ - TransactionID: tid, - TransactionType: nb.GetTransType(), - BlockID: nbid, - Mode: wallet.SendMode, - SenderDID: sc.GetSenderDID(), - ReceiverDID: sc.GetPinningServiceDID(), - Comment: sc.GetComment(), - DateTime: time.Now(), - Status: true, - } - return &td, pl, nil } + //Commented out this unpinning part so that the unpin is not done from the sender side + // for _, t := range ti { + // c.w.UnPin(t.Token, wallet.PrevSenderRole, sc.GetSenderDID()) + // } + //call ipfs repo gc after unpinnning + // c.ipfsRepoGc() nbid, err := nb.GetBlockID(ti[0].Token) if err != nil { c.log.Error("Failed to get block id", "err", err) @@ -1547,6 +1498,17 @@ func (c *Core) pledgeQuorumToken(cr *ConensusRequest, sc *contract.Contract, tid InitiatorSignature: executor_sign, Epoch: cr.TransactionEpoch, } + } else if cr.Mode == PinningServiceMode { + bti.SenderDID = sc.GetSenderDID() + bti.PinningNodeDID = sc.GetPinningServiceDID() + tcb = block.TokenChainBlock{ + TransactionType: block.TokenPinnedAsService, + TokenOwner: sc.GetSenderDID(), + TransInfo: bti, + QuorumSignature: credit, + SmartContract: sc.GetBlock(), + PledgeDetails: ptds, + } } else { //Fetching sender signature to add it to transaction details senderdid := sc.GetSenderDID() diff --git a/core/quorum_validation.go b/core/quorum_validation.go index e4f429cd..5fccc6c8 100644 --- a/core/quorum_validation.go +++ b/core/quorum_validation.go @@ -31,6 +31,7 @@ func (c *Core) validateSigner(b *block.Block, self_did string, p *ipfsport.Peer) c.log.Error("failed to get signers", "err", err) return false, fmt.Errorf("failed to get signers", "err", err) } + c.log.Debug("Signers", signers) for _, signer := range signers { var dc did.DIDCrypto switch b.GetTransType() { From 7b5520e2322cdb895aecf434525f789903d776d6 Mon Sep 17 00:00:00 2001 From: Allen Iype P Cherian Date: Fri, 1 Mar 2024 14:11:07 +0530 Subject: [PATCH 106/129] Fix : Pinning node able to transfer pinned token --- block/block.go | 3 +++ block/transaction.go | 4 ++++ contract/transaction.go | 12 ++++++------ core/quorum_initiator.go | 1 - core/quorum_validation.go | 13 ++++++++----- core/transfer.go | 11 +++++------ 6 files changed, 26 insertions(+), 18 deletions(-) diff --git a/block/block.go b/block/block.go index 771ed5c2..469624c6 100644 --- a/block/block.go +++ b/block/block.go @@ -606,6 +606,9 @@ func (b *Block) GetReceiverDID() string { func (b *Block) GetDeployerDID() string { return b.getTrasnInfoString(TIDeployerDIDKey) } +func (b *Block) GetPinningNodeDID() string { + return b.getTrasnInfoString(TIPinningDIDKey) +} func (b *Block) GetExecutorDID() string { return b.getTrasnInfoString(TIExecutorDIDKey) diff --git a/block/transaction.go b/block/transaction.go index 77ef6421..b07da5b4 100644 --- a/block/transaction.go +++ b/block/transaction.go @@ -43,6 +43,7 @@ const ( TIDeployerDIDKey string = "8" TIExecutorDIDKey string = "9" TICommitedTokensKey string = "10" + TIPinningDIDKey string = "11" ) const ( @@ -124,6 +125,9 @@ func newTransInfo(ctcb map[string]*Block, ti *TransInfo) map[string]interface{} if ti.ReceiverDID != "" { ntib[TIReceiverDIDKey] = ti.ReceiverDID } + if ti.PinningNodeDID != "" { + ntib[TIPinningDIDKey] = ti.PinningNodeDID + } if ti.DeployerDID != "" { ntib[TIDeployerDIDKey] = ti.DeployerDID } diff --git a/contract/transaction.go b/contract/transaction.go index 18d7c55e..23c03166 100644 --- a/contract/transaction.go +++ b/contract/transaction.go @@ -44,12 +44,12 @@ const ( ) type TokenInfo struct { - Token string `json:"token"` - TokenType int `json:"tokenType"` - TokenValue float64 `json:"tokenValue"` - OwnerDID string `json:"ownerDID"` - PinningNodeDID string `json:"pinningNodeDID"` - BlockID string `json:"blockID"` + Token string `json:"token"` + TokenType int `json:"tokenType"` + TokenValue float64 `json:"tokenValue"` + OwnerDID string `json:"ownerDID"` + + BlockID string `json:"blockID"` } type PinInfo struct { diff --git a/core/quorum_initiator.go b/core/quorum_initiator.go index f495dc75..50788b7e 100644 --- a/core/quorum_initiator.go +++ b/core/quorum_initiator.go @@ -647,7 +647,6 @@ func (c *Core) initiateConsensus(cr *ConensusRequest, sc *contract.Contract, dc QuorumList: cr.QuorumList, PinningServiceMode: true, } - c.log.Debug("Send Token Request", sr) var br model.BasicResponse err = rp.SendJSONRequest("POST", APISendReceiverToken, nil, &sr, &br, true) if err != nil { diff --git a/core/quorum_validation.go b/core/quorum_validation.go index 5fccc6c8..160477f9 100644 --- a/core/quorum_validation.go +++ b/core/quorum_validation.go @@ -222,11 +222,14 @@ func (c *Core) validateTokenOwnership(cr *ConensusRequest, sc *contract.Contract return false, fmt.Errorf("Invalid token chain block for ", ti[i].Token) } c.log.Info("Validating token ownership", "token", ti[i].Token, "owner", b.GetOwner(), "sender", sc.GetSenderDID()) - for _, token := range ti { - ownerDID := token.OwnerDID - c.log.Debug("OwnerDID:", ownerDID) - if ownerDID != sc.GetSenderDID() { - c.log.Error("Invalid token owner : The token is Pinned as a service", "owner", b.GetOwner(), "The node which is trying to transfer", sc.GetSenderDID()) + pinningNodeDID := b.GetPinningNodeDID() + ownerDID := b.GetOwner() + senderDID := sc.GetSenderDID() + + if pinningNodeDID != "" { + c.log.Info("The token is Pinned as a service on Node ", pinningNodeDID) + if ownerDID != senderDID { + c.log.Error("Invalid token owner: The token is Pinned as a service", "owner", ownerDID, "The node which is trying to transfer", senderDID) return false } } diff --git a/core/transfer.go b/core/transfer.go index 206ad060..7b766671 100644 --- a/core/transfer.go +++ b/core/transfer.go @@ -415,12 +415,11 @@ func (c *Core) initiatePinRBT(reqID string, req *model.RBTPinRequest) *model.Bas } //OwnerDID will be the same as the sender, so that ownership is not changed. ti := contract.TokenInfo{ - Token: wt[i].TokenID, - TokenType: tt, - TokenValue: wt[i].TokenValue, - OwnerDID: did, - PinningNodeDID: wt[i].DID, - BlockID: bid, + Token: wt[i].TokenID, + TokenType: tt, + TokenValue: wt[i].TokenValue, + OwnerDID: did, + BlockID: bid, } tis = append(tis, ti) From d400d8993a65d5c7c6cb9c6458a43787faf0ad10 Mon Sep 17 00:00:00 2001 From: Allen Iype P Cherian Date: Thu, 30 May 2024 12:34:08 +0530 Subject: [PATCH 107/129] Fix: Missed params and checks during rebase --- core/quorum_initiator.go | 53 +++++--------------- core/quorum_validation.go | 2 +- core/transfer.go | 101 ++++++++++++++++++++++++++++++++------ core/wallet/token.go | 2 +- 4 files changed, 99 insertions(+), 59 deletions(-) diff --git a/core/quorum_initiator.go b/core/quorum_initiator.go index 50788b7e..2316749c 100644 --- a/core/quorum_initiator.go +++ b/core/quorum_initiator.go @@ -111,12 +111,12 @@ type UpdatePledgeRequest struct { } type SendTokenRequest struct { - Address string `json:"peer_id"` - TokenInfo []contract.TokenInfo `json:"token_info"` - TokenChainBlock []byte `json:"token_chain_block"` - QuorumList []string `json:"quorum_list"` - QuorumInfo []QuorumDIDPeerMap `json:"quorum_info"` - TransactionEpoch int `json:"transaction_epoch"` + Address string `json:"peer_id"` + TokenInfo []contract.TokenInfo `json:"token_info"` + TokenChainBlock []byte `json:"token_chain_block"` + QuorumList []string `json:"quorum_list"` + QuorumInfo []QuorumDIDPeerMap `json:"quorum_info"` + TransactionEpoch int `json:"transaction_epoch"` PinningServiceMode bool `json:"pinning_service_mode"` } @@ -454,11 +454,11 @@ func (c *Core) initiateConsensus(cr *ConensusRequest, sc *contract.Contract, dc } defer rp.Close() sr := SendTokenRequest{ - Address: cr.SenderPeerID + "." + sc.GetSenderDID(), - TokenInfo: ti, - TokenChainBlock: nb.GetBlock(), - QuorumList: cr.QuorumList, - TransactionEpoch: cr.TransactionEpoch, + Address: cr.SenderPeerID + "." + sc.GetSenderDID(), + TokenInfo: ti, + TokenChainBlock: nb.GetBlock(), + QuorumList: cr.QuorumList, + TransactionEpoch: cr.TransactionEpoch, PinningServiceMode: false, } @@ -565,35 +565,6 @@ func (c *Core) initiateConsensus(cr *ConensusRequest, sc *contract.Contract, dc c.log.Error("Pledge finlaity not achieved", "err", err) return nil, nil, pledgeFinalityError } - - //Checking prev block details (i.e. the latest block before transferring) by sender. Sender will connect with old quorums, and update about the exhausted token state hashes to quorums for them to unpledge their tokens. - for _, tokeninfo := range ti { - b := c.w.GetLatestTokenBlock(tokeninfo.Token, tokeninfo.TokenType) - signers, _ := b.GetSigner() - - //if signer is similar to sender did skip this token, as the block is the genesys block - if signers[0] == sc.GetSenderDID() { - continue - } - //concat tokenId and BlockID - bid, _ := b.GetBlockID(tokeninfo.Token) - prevtokenIDTokenStateData := tokeninfo.Token + bid - prevtokenIDTokenStateBuffer := bytes.NewBuffer([]byte(prevtokenIDTokenStateData)) - - //add to ipfs get only the hash of the token+tokenstate. This is the hash just before transferring i.e. the exhausted token state hash, and updating in Sender side - prevtokenIDTokenStateHash, _ := c.ipfs.Add(prevtokenIDTokenStateBuffer, ipfsnode.Pin(false), ipfsnode.OnlyHash(true)) - - //send this exhausted hash to old quorums to unpledge - for _, signer := range signers { - signer_peeerId := c.w.GetPeerID(signer) - signer_addr := signer_peeerId + "." + signer - p, _ := c.getPeer(signer_addr, "") - m := make(map[string]string) - m["tokenIDTokenStateHash"] = prevtokenIDTokenStateHash - _ = p.SendJSONRequest("POST", APIUpdateTokenHashDetails, m, nil, nil, true) - } - } - err = c.w.TokensTransferred(sc.GetSenderDID(), ti, nb, rp.IsLocal()) if err != nil { c.log.Error("Failed to transfer tokens", "err", err) @@ -630,7 +601,7 @@ func (c *Core) initiateConsensus(cr *ConensusRequest, sc *contract.Contract, dc } return &td, pl, nil - } else if cr.Mode == PinningServiceMode { + case PinningServiceMode: c.log.Debug("Mode = PinningServiceMode ") c.log.Debug("Pinning Node PeerId", cr.PinningNodePeerID) c.log.Debug("Pinning Service DID", sc.GetPinningServiceDID()) diff --git a/core/quorum_validation.go b/core/quorum_validation.go index 160477f9..50521ac7 100644 --- a/core/quorum_validation.go +++ b/core/quorum_validation.go @@ -230,7 +230,7 @@ func (c *Core) validateTokenOwnership(cr *ConensusRequest, sc *contract.Contract c.log.Info("The token is Pinned as a service on Node ", pinningNodeDID) if ownerDID != senderDID { c.log.Error("Invalid token owner: The token is Pinned as a service", "owner", ownerDID, "The node which is trying to transfer", senderDID) - return false + return false, fmt.Errorf("Invalid token owner: The token is Pinned as a service") } } signatureValidation, err := c.validateSigner(b, quorumDID, p) diff --git a/core/transfer.go b/core/transfer.go index 7b766671..65eb43ef 100644 --- a/core/transfer.go +++ b/core/transfer.go @@ -350,6 +350,16 @@ func (c *Core) initiatePinRBT(reqID string, req *model.RBTPinRequest) *model.Bas resp := &model.BasicResponse{ Status: false, } + + if req.Sender == req.PinningNode { + resp.Message = "Sender and Pinning node cannot be same" + return resp + } + + if !strings.Contains(req.Sender, ".") || !strings.Contains(req.PinningNode, ".") { + resp.Message = "Sender and Pinning Node address should be of the format PeerID.DID" + return resp + } _, did, ok := util.ParseAddress(req.Sender) if !ok { resp.Message = "Invalid sender DID" @@ -361,25 +371,83 @@ func (c *Core) initiatePinRBT(reqID string, req *model.RBTPinRequest) *model.Bas resp.Message = "Invalid pinning DID" return resp } + + if req.TokenCount < MinTrnxAmt { + resp.Message = "Input transaction amount is less than minimum transaction amount" + return resp + } + + decimalPlaces := strconv.FormatFloat(req.TokenCount, 'f', -1, 64) + decimalPlacesStr := strings.Split(decimalPlaces, ".") + if len(decimalPlacesStr) == 2 && len(decimalPlacesStr[1]) > MaxDecimalPlaces { + c.log.Error("Transaction amount exceeds %d decimal places.\n", MaxDecimalPlaces) + resp.Message = fmt.Sprintf("Transaction amount exceeds %d decimal places.\n", MaxDecimalPlaces) + return resp + } + dc, err := c.SetupDID(reqID, did) if err != nil { resp.Message = "Failed to setup DID, " + err.Error() return resp } + + accountBalance, err := c.GetAccountInfo(did) + if err != nil { + c.log.Error("Failed to get tokens", "err", err) + resp.Message = "Insufficient tokens or tokens are locked or " + err.Error() + return resp + } else { + if req.TokenCount > accountBalance.RBTAmount { + c.log.Error(fmt.Sprint("Insufficient balance, account balance is ", accountBalance.RBTAmount, " trnx value is ", req.TokenCount)) + resp.Message = fmt.Sprint("Insufficient balance, account balance is ", accountBalance.RBTAmount, " trnx value is ", req.TokenCount) + return resp + } + } + + tokensForTxn := make([]wallet.Token, 0) + + reqTokens, remainingAmount, err := c.GetRequiredTokens(did, req.TokenCount) + if err != nil { + c.w.ReleaseTokens(reqTokens) + c.log.Error("Failed to get tokens", "err", err) + resp.Message = "Insufficient tokens or tokens are locked or " + err.Error() + return resp + } + if len(reqTokens) != 0 { + tokensForTxn = append(tokensForTxn, reqTokens...) + } + // Get the required tokens from the DID bank // this method locks the token needs to be released or // removed once it done with the transfer - wt, err := c.GetTokens(dc, did, req.TokenCount) - if err != nil { - c.log.Error("Failed to get tokens", "err", err) - resp.Message = "Insufficient tokens or tokens are locked" + if remainingAmount > 0 { + wt, err := c.GetTokens(dc, did, remainingAmount) + if err != nil { + c.log.Error("Failed to get tokens", "err", err) + resp.Message = "Insufficient tokens or tokens are locked" + return resp + } + if len(wt) != 0 { + tokensForTxn = append(tokensForTxn, wt...) + } + } + + var sumOfTokensForTxn float64 + for _, tokenForTxn := range tokensForTxn { + sumOfTokensForTxn = sumOfTokensForTxn + tokenForTxn.TokenValue + sumOfTokensForTxn = floatPrecision(sumOfTokensForTxn, MaxDecimalPlaces) + } + + if sumOfTokensForTxn != req.TokenCount { + c.log.Error(fmt.Sprint("Sum of Selected Tokens sum : ", sumOfTokensForTxn, " is not equal to trnx value : ", req.TokenCount)) + resp.Message = fmt.Sprint("Sum of Selected Tokens sum : ", sumOfTokensForTxn, " is not equal to trnx value : ", req.TokenCount) return resp } // release the locked tokens before exit - defer c.w.ReleaseTokens(wt) + defer c.w.ReleaseTokens(tokensForTxn) - for i := range wt { - c.w.Pin(wt[i].TokenID, wallet.PinningRole, did) //my comment : In this pin function the wallet.OwnerRole is changed to wallet.PinRole + for i := range tokensForTxn { + c.w.Pin(tokensForTxn[i].TokenID, wallet.PinningRole, did, "TID-Not Generated", req.Sender, req.PinningNode, tokensForTxn[i].TokenValue) //my comment : In this pin function the wallet.OwnerRole is changed to wallet.PinRole } p, err := c.getPeer(req.PinningNode) if err != nil { @@ -389,25 +457,25 @@ func (c *Core) initiatePinRBT(reqID string, req *model.RBTPinRequest) *model.Bas defer p.Close() wta := make([]string, 0) - for i := range wt { - wta = append(wta, wt[i].TokenID) + for i := range tokensForTxn { + wta = append(wta, tokensForTxn[i].TokenID) } tis := make([]contract.TokenInfo, 0) - for i := range wt { + for i := range tokensForTxn { tts := "rbt" - if wt[i].TokenValue != 1 { + if tokensForTxn[i].TokenValue != 1 { tts = "part" } tt := c.TokenType(tts) - blk := c.w.GetLatestTokenBlock(wt[i].TokenID, tt) + blk := c.w.GetLatestTokenBlock(tokensForTxn[i].TokenID, tt) if blk == nil { c.log.Error("failed to get latest block, invalid token chain") resp.Message = "failed to get latest block, invalid token chain" return resp } - bid, err := blk.GetBlockID(wt[i].TokenID) + bid, err := blk.GetBlockID(tokensForTxn[i].TokenID) if err != nil { c.log.Error("failed to get block id", "err", err) resp.Message = "failed to get block id, " + err.Error() @@ -415,9 +483,9 @@ func (c *Core) initiatePinRBT(reqID string, req *model.RBTPinRequest) *model.Bas } //OwnerDID will be the same as the sender, so that ownership is not changed. ti := contract.TokenInfo{ - Token: wt[i].TokenID, + Token: tokensForTxn[i].TokenID, TokenType: tt, - TokenValue: wt[i].TokenValue, + TokenValue: tokensForTxn[i].TokenValue, OwnerDID: did, BlockID: bid, } @@ -434,6 +502,7 @@ func (c *Core) initiatePinRBT(reqID string, req *model.RBTPinRequest) *model.Bas Comment: req.Comment, TransTokens: tis, }, + ReqID: reqID, } sc := contract.CreateNewContract(sct) err = sc.UpdateSignature(dc) @@ -448,7 +517,7 @@ func (c *Core) initiatePinRBT(reqID string, req *model.RBTPinRequest) *model.Bas SenderPeerID: c.peerID, PinningNodePeerID: pinningNodepeerid, ContractBlock: sc.GetBlock(), - Mode: 6, + Mode: PinningServiceMode, } td, _, err := c.initiateConsensus(cr, sc, dc) if err != nil { diff --git a/core/wallet/token.go b/core/wallet/token.go index 6b9ff1a6..0df11f28 100644 --- a/core/wallet/token.go +++ b/core/wallet/token.go @@ -494,7 +494,7 @@ func (w *Wallet) TokensReceived(did string, ti []contract.TokenInfo, b *block.Bl receiverAddress := receiverPeerId + "." + b.GetReceiverDID() // Pin the token - ok, err := w.Pin(tokenInfo.Token, role, did, b.GetTid(), senderAddress, receiverAddress, ti[i].TokenValue) + ok, err := w.Pin(tokenInfo.Token, role, did, b.GetTid(), senderAddress, receiverAddress, tokenInfo.TokenValue) if err != nil { return nil, err } From 6b0e2a907510585101dadafcaa7fa526f12e8532 Mon Sep 17 00:00:00 2001 From: Allen Iype P Cherian Date: Mon, 8 Jul 2024 14:47:06 +0530 Subject: [PATCH 108/129] Add feature: Recover token and token chain --- client/recover.go | 18 ++ command/command.go | 4 + command/recover.go | 22 ++ core/core.go | 1 + core/model/tokens.go | 7 + core/part_token.go | 4 +- core/quorum_initiator.go | 3 +- core/quorum_recv.go | 2 +- core/recover.go | 318 ++++++++++++++++++++++++ core/smart_contract_token_operations.go | 2 +- core/token.go | 11 +- core/transfer.go | 26 +- core/wallet/token.go | 51 +++- core/wallet/transaction_history.go | 1 + server/server.go | 1 + server/tokens.go | 36 +++ setup/setup.go | 1 + 17 files changed, 478 insertions(+), 30 deletions(-) create mode 100644 client/recover.go create mode 100644 command/recover.go create mode 100644 core/recover.go diff --git a/client/recover.go b/client/recover.go new file mode 100644 index 00000000..262a07cf --- /dev/null +++ b/client/recover.go @@ -0,0 +1,18 @@ +package client + +import ( + "time" + + "github.com/rubixchain/rubixgoplatform/core/model" + "github.com/rubixchain/rubixgoplatform/setup" +) + +func (c *Client) RecoverRBT(rt *model.RBTRecoverRequest) (*model.BasicResponse, error) { + var br model.BasicResponse + err := c.sendJSONRequest("POST", setup.APIRecoverRBT, nil, rt, &br, time.Minute*2) + if err != nil { + c.log.Error("Failed to Recover RBT from the pinning node", "err", err) + return nil, err + } + return &br, nil +} diff --git a/command/command.go b/command/command.go index e0490efa..c855d188 100644 --- a/command/command.go +++ b/command/command.go @@ -89,6 +89,7 @@ const ( RunUnpledge string = "run-unpledge" UnpledgePOWPledgeTokens string = "unpledge-pow-pledge-tokens" PinRBTCmd string = "pinrbt" + RecoverTokensCmd string = "recovertokens" ) var commands = []string{VersionCmd, @@ -139,6 +140,7 @@ var commands = []string{VersionCmd, RunUnpledge, UnpledgePOWPledgeTokens, PinRBTCmd, + RecoverTokensCmd, } var commandsHelp = []string{"To get tool version", @@ -637,6 +639,8 @@ func Run(args []string) { cmd.UnpledgePOWBasedPledgedTokens() case PinRBTCmd: cmd.PinRBT() + case RecoverTokensCmd: + cmd.RecoverTokens() default: cmd.log.Error("Invalid command") } diff --git a/command/recover.go b/command/recover.go new file mode 100644 index 00000000..4ed9f5a1 --- /dev/null +++ b/command/recover.go @@ -0,0 +1,22 @@ +package command + +import ( + "github.com/rubixchain/rubixgoplatform/core/model" +) + +func (cmd *Command) RecoverTokens() { + rt := model.RBTRecoverRequest{ + PinningNode: cmd.pinningAddress, + Sender: cmd.senderAddr, + TokenCount: cmd.rbtAmount, + } + + br, err := cmd.c.RecoverRBT(&rt) + if err != nil { + cmd.log.Error("Failed to Recover the Tokens", "err", err) + return + } + cmd.log.Info("The message response from RecoverRBT function", br.Message) + cmd.log.Info("The status in RecoverRBT function", br.Status) + cmd.log.Info("RBT Recovered successfully") +} diff --git a/core/core.go b/core/core.go index 9ee60f6b..6f59c95c 100644 --- a/core/core.go +++ b/core/core.go @@ -52,6 +52,7 @@ const ( APIUpdateTokenHashDetails string = "/api/update-tokenhash-details" APIAddUnpledgeDetails string = "/api/initiate-unpledge" APISelfTransfer string = "/api/self-transfer" + APIRecoverPinnedRBT string = "/api/recover-pinned-rbt" ) const ( diff --git a/core/model/tokens.go b/core/model/tokens.go index 955c0627..3e6596d0 100644 --- a/core/model/tokens.go +++ b/core/model/tokens.go @@ -29,6 +29,13 @@ type RBTPinRequest struct { Password string `json:"password"` } +type RBTRecoverRequest struct { + PinningNode string `json:"pinningNode"` + Sender string `json:"sender"` + TokenCount float64 `json:"tokenCount"` + Password string `json:"password"` +} + type RBTTransferReply struct { BasicResponse Receiver string `json:"receiver"` diff --git a/core/part_token.go b/core/part_token.go index 50c3f13e..094fd4e0 100644 --- a/core/part_token.go +++ b/core/part_token.go @@ -37,7 +37,7 @@ func CeilfloatPrecision(num float64, precision int) float64 { return float64(Ceilround(num*output)) / output } -func (c *Core) GetTokens(dc did.DIDCrypto, did string, value float64) ([]wallet.Token, error) { +func (c *Core) GetTokens(dc did.DIDCrypto, did string, value float64, trnxMode int) ([]wallet.Token, error) { wholeValue := int(value) var err error fv := float64(wholeValue) @@ -46,7 +46,7 @@ func (c *Core) GetTokens(dc did.DIDCrypto, did string, value float64) ([]wallet. remWhole := 0 wt := make([]wallet.Token, 0) if wholeValue != 0 { - wt, remWhole, err = c.w.GetWholeTokens(did, wholeValue) + wt, remWhole, err = c.w.GetWholeTokens(did, wholeValue, trnxMode) if err != nil { c.log.Error("failed to get token", "err", err) return nil, err diff --git a/core/quorum_initiator.go b/core/quorum_initiator.go index 2316749c..b2fd1c89 100644 --- a/core/quorum_initiator.go +++ b/core/quorum_initiator.go @@ -172,6 +172,7 @@ func (c *Core) QuroumSetup() { c.l.AddRoute(APIUnlockTokens, "POST", c.unlockTokens) c.l.AddRoute(APIUpdateTokenHashDetails, "POST", c.updateTokenHashDetails) c.l.AddRoute(APIAddUnpledgeDetails, "POST", c.addUnpledgeDetails) + c.l.AddRoute(APIRecoverPinnedRBT, "POST", c.recoverPinnedToken) if c.arbitaryMode { c.l.AddRoute(APIMapDIDArbitration, "POST", c.mapDIDArbitration) c.l.AddRoute(APICheckDIDArbitration, "GET", c.chekDIDArbitration) @@ -649,7 +650,7 @@ func (c *Core) initiateConsensus(cr *ConensusRequest, sc *contract.Contract, dc TransactionID: tid, TransactionType: nb.GetTransType(), BlockID: nbid, - Mode: wallet.SendMode, + Mode: wallet.PinningServiceMode, SenderDID: sc.GetSenderDID(), ReceiverDID: sc.GetPinningServiceDID(), Comment: sc.GetComment(), diff --git a/core/quorum_recv.go b/core/quorum_recv.go index 93f9afb6..e93c58b0 100644 --- a/core/quorum_recv.go +++ b/core/quorum_recv.go @@ -592,7 +592,7 @@ func (c *Core) reqPledgeToken(req *ensweb.Request) *ensweb.Result { } dc := c.pqc[did] - wt, err := c.GetTokens(dc, did, pr.TokensRequired) + wt, err := c.GetTokens(dc, did, pr.TokensRequired, RBTTransferMode) if err != nil { crep.Message = "Failed to get tokens" return c.l.RenderJSON(req, &crep, http.StatusOK) diff --git a/core/recover.go b/core/recover.go new file mode 100644 index 00000000..2ec20945 --- /dev/null +++ b/core/recover.go @@ -0,0 +1,318 @@ +package core + +import ( + "encoding/json" + "fmt" + "net/http" + "strconv" + "strings" + + "github.com/rubixchain/rubixgoplatform/block" + "github.com/rubixchain/rubixgoplatform/contract" + "github.com/rubixchain/rubixgoplatform/core/model" + "github.com/rubixchain/rubixgoplatform/core/wallet" + signModule "github.com/rubixchain/rubixgoplatform/did" + "github.com/rubixchain/rubixgoplatform/util" + "github.com/rubixchain/rubixgoplatform/wrapper/ensweb" +) + +type SendRecoverRequest struct { + Address string `json:"peer_id"` + Signature signModule.DIDSignature `json:"Signature"` +} + +func (c *Core) InitiateRecoverRBT(reqID string, req *model.RBTRecoverRequest) { + br := c.initiateRecoverRBT(reqID, req) + fmt.Println("Request ID in InitiateRecoverRBT:", reqID) + dc := c.GetWebReq(reqID) + if dc == nil { + c.log.Error("Failed to get did channels") + return + } + dc.OutChan <- br +} + +func (c *Core) initiateRecoverRBT(reqID string, req *model.RBTRecoverRequest) *model.BasicResponse { + + fmt.Println("Initiate Recover RBT Called ") + resp := &model.BasicResponse{ + Status: false, + } + + if req.Sender == req.PinningNode { + resp.Message = "Sender and Pinning node cannot be same" + return resp + } + + if !strings.Contains(req.Sender, ".") || !strings.Contains(req.PinningNode, ".") { + resp.Message = "Sender and Pinning Node address should be of the format PeerID.DID" + return resp + } + _, did, ok := util.ParseAddress(req.Sender) + if !ok { + resp.Message = "Invalid sender DID" + return resp + } + + pinningNodepeerid, pinningNodeDID, ok := util.ParseAddress(req.PinningNode) + fmt.Println("Pinning node:", pinningNodeDID, pinningNodepeerid) + if !ok { + resp.Message = "Invalid pinning DID" + return resp + } + + if req.TokenCount < MinTrnxAmt { + resp.Message = "Input transaction amount is less than minimum transaction amount" + return resp + } + + decimalPlaces := strconv.FormatFloat(req.TokenCount, 'f', -1, 64) + decimalPlacesStr := strings.Split(decimalPlaces, ".") + if len(decimalPlacesStr) == 2 && len(decimalPlacesStr[1]) > MaxDecimalPlaces { + c.log.Error("Transaction amount exceeds %d decimal places.\n", MaxDecimalPlaces) + resp.Message = fmt.Sprintf("Transaction amount exceeds %d decimal places.\n", MaxDecimalPlaces) + return resp + } + + dc, err := c.SetupDID(reqID, did) + fmt.Println("dc", dc) + if err != nil { + resp.Message = "Failed to setup DID, " + err.Error() + return resp + } + p, err := c.getPeer(req.PinningNode) + fmt.Println("P in getPeer :", p) + if err != nil { + resp.Message = "Failed to get pinning peer, " + err.Error() + return resp + } + defer p.Close() + var signFunc *signModule.DIDLite + if req.Password == "" { + signFunc = signModule.InitDIDLiteWithPassword(did, c.didDir, "mypassword") + } else { + signFunc = signModule.InitDIDLiteWithPassword(did, c.didDir, req.Password) + } + //signFunc := signModule.InitDIDLiteWithPassword(did, c.didDir, "mypassword") + fmt.Println("c.didDIR", c.didDir) + pvtSign, err := signFunc.PvtSign([]byte(did)) + fmt.Println("DID in initiateRecoverRBT", did) + fmt.Println("PVTSIGN in initiate Recover RBT", pvtSign) + fmt.Println("Error in initiateRecoverRBT", err) + signature := signModule.DIDSignature{ + Pixels: []byte{}, + Signature: pvtSign, + } + sr := SendRecoverRequest{ + Address: req.Sender, + Signature: signature, + } + var br model.BasicResponse + err = p.SendJSONRequest("POST", APIRecoverPinnedRBT, nil, &sr, &br, true) + if err != nil { + c.log.Error("Unable to send tokens to receiver", "err", err) + return nil + } + + fmt.Println(br.Message) + fmt.Println(br.Result) + fmt.Println(br.Status) + + fmt.Printf("Type: %T, Value: %v\n", br.Result, br.Result) + + //tokenlist := br.Result + retrieved, ok := br.Result.([]interface{}) + if !ok { + fmt.Println("Failed to retrieve slice from interface") + } + // Convert []interface{} to []TokenInfo + var tokenInfos []contract.TokenInfo + for _, item := range retrieved { + if m, ok := item.(map[string]interface{}); ok { + tokenInfo := mapToTokenInfo(m) + tokenInfos = append(tokenInfos, tokenInfo) + } + } + + // Print the retrieved data + fmt.Println("Successfully retrieved TokenInfo slice from interface:") + for i, tokenInfo := range tokenInfos { + fmt.Printf("TokenInfo %d: %+v\n", i, tokenInfo) + fmt.Printf("Block ID: %s\n", tokenInfo.BlockID) + fmt.Printf("Owner DID: %s\n", tokenInfo.OwnerDID) + fmt.Printf("Token: %s\n", tokenInfo.Token) + fmt.Printf("Token Type: %d\n", tokenInfo.TokenType) + fmt.Printf("Token Value: %f\n", tokenInfo.TokenValue) + + token := tokenInfo.Token + tokenType := tokenInfo.TokenType + blockID := tokenInfo.BlockID + + // Perform your desired operation with the extracted fields + // For example, just print them + fmt.Printf("Token: %s, TokenType: %d, BlockID: %s\n", token, tokenType, blockID) + + tr := TCBSyncRequest{ + Token: token, + TokenType: tokenType, + BlockID: "", + } + + var trep TCBSyncReply + + err = p.SendJSONRequest("POST", APISyncTokenChain, nil, &tr, &trep, false) + if err != nil { + c.log.Error("Failed to sync token chain block", "err", err) + } + if !trep.Status { + c.log.Error("Failed to sync token chain block", "msg", trep.Message) + } + + fmt.Println("The response from the json request ", trep) + for _, bb := range trep.TCBlock { + blk := block.InitBlock(bb, nil) + if blk == nil { + c.log.Error("Failed to add token chain block, invalid block, sync failed", "err", err) + } + fmt.Println("The block is ", blk) + err = c.w.AddTokenBlock(token, blk) + if err != nil { + c.log.Error("Failed to add token chain block, syncing failed", "err", err) + } + } + var pt string + if c.TokenType(PartString) == tokenType { + gb := c.w.GetGenesisTokenBlock(token, tokenType) + if gb == nil { + c.log.Error("failed to get genesis block for token ", token) + } else { + pt, _, err = gb.GetParentDetials(token) + if err != nil { + c.log.Error("failed to get parent details for token ", token, "err : ", err) + pt = "" // Ensure pt is reset to empty string if an error occurs + } + } + err = c.syncParentToken(p, pt) + if err != nil { + c.log.Error("Failed to sync parent token chain while recovering token", err) + + } + + } + + tokenDetails := wallet.Token{ + TokenID: token, + ParentTokenID: pt, + TokenValue: tokenInfo.TokenValue, + DID: tokenInfo.OwnerDID, + TokenStatus: wallet.TokenIsFree, + } + c.w.CreateToken(&tokenDetails) + } + + c.log.Info("Tokens recovered successfully") + resp.Status = true + msg := "Tokens recovered successfully" + resp.Message = msg + return resp +} + +func (c *Core) recoverPinnedToken(req *ensweb.Request) *ensweb.Result { + pinNodeDid := c.l.GetQuerry(req, "did") + fmt.Println("DID in recoverPinnedToken :", pinNodeDid) + var sr SendRecoverRequest + err := c.l.ParseJSON(req, &sr) + crep := model.BasicResponse{ + Status: false, + } + fmt.Println("SR in recover Pinned Token :", sr) + if err != nil { + c.log.Error("Failed to parse json request", "err", err) + crep.Message = "Failed to parse json request" + return c.l.RenderJSON(req, &crep, http.StatusOK) + } + p, err := c.getPeer(sr.Address) + if err != nil { + c.log.Error("failed to get peer", "err", err) + crep.Message = "failed to get peer" + return c.l.RenderJSON(req, &crep, http.StatusOK) + } + defer p.Close() + _, recoverNodeDID, _ := util.ParseAddress(sr.Address) + recoveredTokens, err := c.w.GetAllPinnedTokens(recoverNodeDID) + fmt.Println("recoverDID in recoverPinnedToken :", recoverNodeDID) + fmt.Println("Recovered Tokens in the Pinned Node :", recoveredTokens) + fmt.Println("Err in recoveredTokens:", err) + + signFunc := signModule.InitDIDLite(recoverNodeDID, c.didDir, nil) + fmt.Println("The directory in recoverPinnedToken", c.didDir) + verified, err := signFunc.PvtVerify([]byte(recoverNodeDID), sr.Signature.Signature) + fmt.Println("Verified in recoverPinnedToken", verified) + fmt.Println("Err in recoverPinnedToken", err) + tis := make([]contract.TokenInfo, 0) + for i := range recoveredTokens { + tts := "rbt" + if recoveredTokens[i].TokenValue != 1 { + tts = "part" + } + tt := c.TokenType(tts) + blk := c.w.GetLatestTokenBlock(recoveredTokens[i].TokenID, tt) + if blk == nil { + c.log.Error("failed to get latest block, invalid token chain") + crep.Message = "failed to get latest block, invalid token chain" + } + bid, err := blk.GetBlockID(recoveredTokens[i].TokenID) + if err != nil { + c.log.Error("failed to get block id", "err", err) + crep.Message = "failed to get block id, " + err.Error() + } + ti := contract.TokenInfo{ + Token: recoveredTokens[i].TokenID, + TokenType: tt, + TokenValue: recoveredTokens[i].TokenValue, + OwnerDID: recoveredTokens[i].DID, + BlockID: bid, + } + tis = append(tis, ti) + } + + fmt.Println("TIS is :", tis) + crep.Status = true + crep.Message = "Token Recovered Succesfully" + crep.Result = tis + return c.l.RenderJSON(req, &crep, http.StatusOK) +} + +func mapToTokenInfo(m map[string]interface{}) contract.TokenInfo { + tokenType, err := m["tokenType"].(json.Number) + if err { + fmt.Println("The error in tokenType is :", err) + } + tokenTypeInt64, err1 := tokenType.Int64() + if err1 != nil { + fmt.Println("The error in tokenTypeInt is :", err1) + } + + fmt.Println("TokenType :", tokenType) + fmt.Println("TokenType Int64 :", tokenTypeInt64) + fmt.Println("Token Type int :", int(tokenTypeInt64)) + + toknValue, err2 := m["tokenValue"].(json.Number) + if err2 { + fmt.Println("The error in tokenValue is :", err2) + } + tokenValueFloat64, err3 := toknValue.Float64() + if err3 != nil { + fmt.Println("The error in tokenValueFloat64 is :", err3) + } + fmt.Println("Token value :", toknValue) + fmt.Println("Token value float64", tokenValueFloat64) + + return contract.TokenInfo{ + Token: m["token"].(string), + TokenType: int(tokenTypeInt64), + TokenValue: tokenValueFloat64, + OwnerDID: m["ownerDID"].(string), + BlockID: m["blockID"].(string), + } +} diff --git a/core/smart_contract_token_operations.go b/core/smart_contract_token_operations.go index fd3edf9d..7aaf51c2 100644 --- a/core/smart_contract_token_operations.go +++ b/core/smart_contract_token_operations.go @@ -51,7 +51,7 @@ func (c *Core) deploySmartContractToken(reqID string, deployReq *model.DeploySma return resp } //Get the RBT details from DB for the associated amount/ if token amount is of PArts create - rbtTokensToCommitDetails, err := c.GetTokens(didCryptoLib, did, deployReq.RBTAmount) + rbtTokensToCommitDetails, err := c.GetTokens(didCryptoLib, did, deployReq.RBTAmount, SmartContractDeployMode) if err != nil { c.log.Error("Failed to retrieve Tokens to be committed", "err", err) resp.Message = "Failed to retrieve Tokens to be committed , err : " + err.Error() diff --git a/core/token.go b/core/token.go index 2d757b43..e70e714f 100644 --- a/core/token.go +++ b/core/token.go @@ -336,7 +336,7 @@ func (c *Core) getFromIPFS(path string) ([]byte, error) { // // c.log.Debug("Token recevied", "token", tp.Token) // } -func (c *Core) GetRequiredTokens(did string, txnAmount float64) ([]wallet.Token, float64, error) { +func (c *Core) GetRequiredTokens(did string, txnAmount float64, txnMode int) ([]wallet.Token, float64, error) { requiredTokens := make([]wallet.Token, 0) var remainingAmount float64 wholeValue := int(txnAmount) @@ -348,7 +348,7 @@ func (c *Core) GetRequiredTokens(did string, txnAmount float64) ([]wallet.Token, if wholeValue != 0 { //extract the whole amount part that is the integer value of txn amount //serach for the required whole amount - wholeTokens, remWhole, err := c.w.GetWholeTokens(did, wholeValue) + wholeTokens, remWhole, err := c.w.GetWholeTokens(did, wholeValue, txnMode) if err != nil && err.Error() != "no records found" { c.w.ReleaseTokens(wholeTokens) c.log.Error("failed to search for whole tokens", "err", err) @@ -516,3 +516,10 @@ func (c *Core) UpdatePledgedTokenInfo(tokenstatehash string) error { } return nil } + +func (c *Core) GetpinnedTokens(did string) ([]wallet.Token, error) { + requiredTokens, err := c.w.GetAllPinnedTokens(did) + fmt.Println("err", err) + fmt.Println("The tokenlist received:", requiredTokens) + return requiredTokens, nil +} diff --git a/core/transfer.go b/core/transfer.go index 65eb43ef..b86286ec 100644 --- a/core/transfer.go +++ b/core/transfer.go @@ -10,6 +10,7 @@ import ( "github.com/rubixchain/rubixgoplatform/core/model" "github.com/rubixchain/rubixgoplatform/core/wallet" "github.com/rubixchain/rubixgoplatform/did" + "github.com/rubixchain/rubixgoplatform/util" "github.com/rubixchain/rubixgoplatform/wrapper/uuid" ) @@ -23,7 +24,6 @@ func (c *Core) InitiateRBTTransfer(reqID string, req *model.RBTTransferRequest) dc.OutChan <- br } - func gatherTokensForTransaction(c *Core, req *model.RBTTransferRequest, dc did.DIDCrypto, isSelfRBTTransfer bool) ([]wallet.Token, error) { var tokensForTransfer []wallet.Token @@ -33,22 +33,22 @@ func gatherTokensForTransaction(c *Core, req *model.RBTTransferRequest, dc did.D if req.TokenCount < MinDecimalValue(MaxDecimalPlaces) { return nil, fmt.Errorf("input transaction amount is less than minimum transaction amount") } - + decimalPlaces := strconv.FormatFloat(req.TokenCount, 'f', -1, 64) decimalPlacesStr := strings.Split(decimalPlaces, ".") if len(decimalPlacesStr) == 2 && len(decimalPlacesStr[1]) > MaxDecimalPlaces { return nil, fmt.Errorf("transaction amount exceeds %v decimal places", MaxDecimalPlaces) } - + accountBalance, err := c.GetAccountInfo(senderDID) if err != nil { return nil, fmt.Errorf("insufficient tokens or tokens are locked or %v", err.Error()) } else { - if req.TokenCount > accountBalance.RBTAmount { + if req.TokenCount > accountBalance.RBTAmount { return nil, fmt.Errorf("insufficient balance, account balance is %v, trnx value is %v", accountBalance.RBTAmount, req.TokenCount) } } - + reqTokens, remainingAmount, err := c.GetRequiredTokens(senderDID, req.TokenCount) if err != nil { c.w.ReleaseTokens(reqTokens) @@ -71,13 +71,13 @@ func gatherTokensForTransaction(c *Core, req *model.RBTTransferRequest, dc did.D tokensForTransfer = append(tokensForTransfer, wt...) } } - + var sumOfTokensForTxn float64 for _, tokenForTransfer := range tokensForTransfer { sumOfTokensForTxn = sumOfTokensForTxn + tokenForTransfer.TokenValue sumOfTokensForTxn = floatPrecision(sumOfTokensForTxn, MaxDecimalPlaces) } - + if sumOfTokensForTxn != req.TokenCount { return nil, fmt.Errorf("sum of Selected Tokens sum : %v is not equal to trnx value : %v", sumOfTokensForTxn, req.TokenCount) } @@ -92,7 +92,7 @@ func gatherTokensForTransaction(c *Core, req *model.RBTTransferRequest, dc did.D } return nil, fmt.Errorf("failed to get free tokens of owner, error: %v", err.Error()) } - + // Get the transaction epoch for every token and chec for _, token := range tokensOwnedBySender { // Nodes running old version of rubixgoplatform will not have their TransactionID column of Tokens's table populated @@ -105,7 +105,7 @@ func gatherTokensForTransaction(c *Core, req *model.RBTTransferRequest, dc did.D return nil, fmt.Errorf("failed to get transaction details for trx hash: %v, err: %v", token.TransactionID, err) } - if time.Now().Unix() - tokenTransactionDetail.Epoch > int64(pledgePeriodInSeconds) { + if time.Now().Unix()-tokenTransactionDetail.Epoch > int64(pledgePeriodInSeconds) { if err := c.w.LockToken(&token); err != nil { return nil, fmt.Errorf("failed to lock tokens %v, exiting selfTransfer routine with error: %v", token.TokenID, err.Error()) } @@ -164,7 +164,7 @@ func getConsensusRequest(consensusRequestType int, senderPeerID string, receiver ContractBlock: contractBlock, TransactionEpoch: transactionEpoch, } - + if isSelfTransfer { consensusRequest.Mode = SelfTransferMode } @@ -275,7 +275,7 @@ func (c *Core) initiateRBTTransfer(reqID string, req *model.RBTTransferRequest) resp.Message = err.Error() return resp } - + cr := getConsensusRequest(req.Type, c.peerID, rpeerid, sc.GetBlock(), txEpoch, isSelfRBTTransfer) td, _, err := c.initiateConsensus(cr, sc, dc) @@ -406,7 +406,7 @@ func (c *Core) initiatePinRBT(reqID string, req *model.RBTPinRequest) *model.Bas tokensForTxn := make([]wallet.Token, 0) - reqTokens, remainingAmount, err := c.GetRequiredTokens(did, req.TokenCount) + reqTokens, remainingAmount, err := c.GetRequiredTokens(did, req.TokenCount, PinningServiceMode) if err != nil { c.w.ReleaseTokens(reqTokens) c.log.Error("Failed to get tokens", "err", err) @@ -421,7 +421,7 @@ func (c *Core) initiatePinRBT(reqID string, req *model.RBTPinRequest) *model.Bas // this method locks the token needs to be released or // removed once it done with the transfer if remainingAmount > 0 { - wt, err := c.GetTokens(dc, did, remainingAmount) + wt, err := c.GetTokens(dc, did, remainingAmount, PinningServiceMode) if err != nil { c.log.Error("Failed to get tokens", "err", err) resp.Message = "Insufficient tokens or tokens are locked" diff --git a/core/wallet/token.go b/core/wallet/token.go index 0df11f28..b3cbadd2 100644 --- a/core/wallet/token.go +++ b/core/wallet/token.go @@ -160,13 +160,21 @@ func (w *Wallet) GetCloserToken(did string, rem float64) (*Token, error) { return &tks[0], nil } -func (w *Wallet) GetWholeTokens(did string, num int) ([]Token, int, error) { +func (w *Wallet) GetWholeTokens(did string, num int, trnxMode int) ([]Token, int, error) { w.l.Lock() defer w.l.Unlock() var t []Token - err := w.s.Read(TokenStorage, &t, "did=? AND (token_status=? OR token_status=?) AND token_value=?", did, TokenIsFree, TokenIsPinnedAsService, 1.0) - if err != nil { - return nil, num, err + if trnxMode == 0 { + err := w.s.Read(TokenStorage, &t, "did=? AND (token_status=? OR token_status=?) AND token_value=?", did, TokenIsFree, TokenIsPinnedAsService, 1.0) + if err != nil { + return nil, num, err + } + } else { + err := w.s.Read(TokenStorage, &t, "did=? AND token_status=? AND token_value=?", did, TokenIsFree, 1.0) + if err != nil { + return nil, num, err + } + } tl := len(t) if tl > num { @@ -178,10 +186,10 @@ func (w *Wallet) GetWholeTokens(did string, num int) ([]Token, int, error) { } for i := range wt { wt[i].TokenStatus = TokenIsLocked - err = w.s.Update(TokenStorage, &wt[i], "did=? AND token_id=?", did, wt[i].TokenID) - if err != nil { - w.log.Error("Failed to update token status", "err", err) - return nil, num, err + err1 := w.s.Update(TokenStorage, &wt[i], "did=? AND token_id=?", did, wt[i].TokenID) + if err1 != nil { + w.log.Error("Failed to update token status", "err", err1) + return nil, num, err1 } } return wt, (num - tl), nil @@ -465,7 +473,7 @@ func (w *Wallet) TokensReceived(did string, ti []contract.TokenInfo, b *block.Bl TokenID: tokenInfo.Token, TokenValue: tokenInfo.TokenValue, ParentTokenID: parentTokenID, - DID: did, + DID: tokenInfo.OwnerDID, } t.TokenStateHash = tokenHashMap[tokenId] @@ -476,13 +484,15 @@ func (w *Wallet) TokensReceived(did string, ti []contract.TokenInfo, b *block.Bl // Update token status and pin tokens tokenStatus := TokenIsFree role := OwnerRole + ownerdid := did if pinningServiceMode { tokenStatus = TokenIsPinnedAsService role = PinningRole + ownerdid = b.GetOwner() } // Update token status - t.DID = did + t.DID = ownerdid t.TokenStatus = tokenStatus t.TransactionID = b.GetTid() t.TokenStateHash = tokenHashMap[t.TokenID] @@ -777,3 +787,24 @@ func (w *Wallet) RemoveTokenStateHashByTransactionID(transactionID string) error return nil } + +func (w *Wallet) GetAllPinnedTokens(did string) ([]Token, error) { + w.l.Lock() + defer w.l.Unlock() + var t []Token + err := w.s.Read(TokenStorage, &t, "did=? AND token_status=? ", did, TokenIsPinnedAsService) + if err != nil { + w.log.Error("Failed to get tokens", "err", err) + return nil, err + } + for i := range t { + t[i].TokenStatus = TokenIsLocked // Here should we change it to TokenIsRecovered + err = w.s.Update(TokenStorage, &t[i], "did=? AND token_id=?", did, t[i].TokenID) + if err != nil { + w.log.Error("Failed to update token status", "err", err) + return nil, err + } + } + return t, nil + +} diff --git a/core/wallet/transaction_history.go b/core/wallet/transaction_history.go index 2ed5791b..318b4f42 100644 --- a/core/wallet/transaction_history.go +++ b/core/wallet/transaction_history.go @@ -11,6 +11,7 @@ const ( RecvMode DeployMode ExecuteMode + PinningServiceMode ) diff --git a/server/server.go b/server/server.go index e830b815..9eb80804 100644 --- a/server/server.go +++ b/server/server.go @@ -167,6 +167,7 @@ func (s *Server) RegisterRoutes() { s.AddRoute(setup.APIRunUnpledge, "POST", s.AuthHandle(s.RunUnpledgeHandle, false, s.AuthError, true)) s.AddRoute(setup.APIUnpledgePOWPledgeTokens, "POST", s.AuthHandle(s.UnpledgePoWBasedPledgedTokens, false, s.AuthError, true)) s.AddRoute(setup.APIInitiatePinRBT, "POST", s.AuthHandle(s.APIInitiatePinRBT, true, s.AuthError, false)) + s.AddRoute(setup.APIRecoverRBT, "POST", s.AuthHandle(s.APIRecoverRBT, true, s.AuthError, false)) } func (s *Server) ExitFunc() error { diff --git a/server/tokens.go b/server/tokens.go index 0fae3b1f..5613f7c0 100644 --- a/server/tokens.go +++ b/server/tokens.go @@ -110,6 +110,42 @@ func (s *Server) APIInitiatePinRBT(req *ensweb.Request) *ensweb.Result { return s.didResponse(req, req.ID) } +type RBTRecoverRequestSwaggoInput struct { + PinningNode string `json:"pinningNode"` + Sender string `json:"sender"` + TokenCount float64 `json:"tokenCOunt"` + Password string `json:"password"` +} + +// ShowAccount godoc +// @Summary Recover RBT Token and Tokenchain from the pinning node +// @Description This API will recover token and tokenchain from the Pinning node to the node which has pinned the token +// @Tags Account +// @ID recover-rbt +// @Accept json +// @Produce json +// @Param input body RBTRecoverRequestSwaggoInput true "Recover-RBT" +// @Success 200 {object} model.BasicResponse +// @Router /api/api/recover-rbt [post] + +func (s *Server) APIRecoverRBT(req *ensweb.Request) *ensweb.Result { + var rbtReq model.RBTRecoverRequest + err := s.ParseJSON(req, &rbtReq) + if err != nil { + return s.BasicResponse(req, false, "Invalid input", nil) + } + _, did, ok := util.ParseAddress(rbtReq.Sender) + if !ok { + return s.BasicResponse(req, false, "Invalid sender address", nil) + } + if !s.validateDIDAccess(req, did) { + return s.BasicResponse(req, false, "DID does not have an access", nil) + } + s.c.AddWebReq(req) + go s.c.InitiateRecoverRBT(req.ID, &rbtReq) + return s.didResponse(req, req.ID) +} + // ShowAccount godoc // @Summary Check account balance // @Description For a mentioned DID, check the account balance diff --git a/setup/setup.go b/setup/setup.go index 57d58bd9..23bca5fe 100644 --- a/setup/setup.go +++ b/setup/setup.go @@ -74,6 +74,7 @@ const ( APIRunUnpledge string = "/api/run-unpledge" APIUnpledgePOWPledgeTokens string = "/api/unpledge-pow-unpledge-tokens" APIInitiatePinRBT string = "/api/initiate-pin-rbt" + APIRecoverRBT string = "/api/recover-rbt" ) // jwt.RegisteredClaims From c14f3d74e876b9a28df4769548367386f5ce1788 Mon Sep 17 00:00:00 2001 From: Allen Iype P Cherian Date: Wed, 10 Jul 2024 17:30:30 +0530 Subject: [PATCH 109/129] Remove debug and minor fixes --- command/did.go | 2 +- command/recover.go | 8 ++- core/model/tokens.go | 1 + core/quorum_initiator.go | 2 +- core/recover.go | 132 +++++++++++---------------------------- core/token.go | 9 ++- core/transfer.go | 27 +++----- 7 files changed, 62 insertions(+), 119 deletions(-) diff --git a/command/did.go b/command/did.go index 00cb9229..c4872226 100644 --- a/command/did.go +++ b/command/did.go @@ -332,6 +332,6 @@ func (cmd *Command) GetAccountInfo() { cmd.log.Error("Failed to get account info", "message", info.Message) } else { cmd.log.Info("Successfully got the account information") - fmt.Printf("RBT : %10.5f, Locked RBT : %10.5f, Pledged RBT : %10.5f\n", info.AccountInfo[0].RBTAmount, info.AccountInfo[0].LockedRBT, info.AccountInfo[0].PledgedRBT) + fmt.Printf("RBT : %10.5f, Locked RBT : %10.5f, Pledged RBT : %10.5f, Pinned RBT : %10.5f\n", info.AccountInfo[0].RBTAmount, info.AccountInfo[0].LockedRBT, info.AccountInfo[0].PledgedRBT, info.AccountInfo[0].PinnedRBT) } } diff --git a/command/recover.go b/command/recover.go index 4ed9f5a1..9ab2b7df 100644 --- a/command/recover.go +++ b/command/recover.go @@ -16,7 +16,9 @@ func (cmd *Command) RecoverTokens() { cmd.log.Error("Failed to Recover the Tokens", "err", err) return } - cmd.log.Info("The message response from RecoverRBT function", br.Message) - cmd.log.Info("The status in RecoverRBT function", br.Status) - cmd.log.Info("RBT Recovered successfully") + if !br.Status { + cmd.log.Error("Failed to recover RBT: " + br.Message) + } else { + cmd.log.Info("Recovered RBT: " + br.Message) + } } diff --git a/core/model/tokens.go b/core/model/tokens.go index 3e6596d0..21d76652 100644 --- a/core/model/tokens.go +++ b/core/model/tokens.go @@ -56,6 +56,7 @@ type DIDAccountInfo struct { RBTAmount float64 `json:"rbt_amount"` PledgedRBT float64 `json:"pledged_rbt"` LockedRBT float64 `json:"locked_rbt"` + PinnedRBT float64 `json:"pinned_rbt"` } type TokenDetail struct { diff --git a/core/quorum_initiator.go b/core/quorum_initiator.go index b2fd1c89..ae4bcc11 100644 --- a/core/quorum_initiator.go +++ b/core/quorum_initiator.go @@ -606,7 +606,7 @@ func (c *Core) initiateConsensus(cr *ConensusRequest, sc *contract.Contract, dc c.log.Debug("Mode = PinningServiceMode ") c.log.Debug("Pinning Node PeerId", cr.PinningNodePeerID) c.log.Debug("Pinning Service DID", sc.GetPinningServiceDID()) - rp, err := c.getPeer(cr.PinningNodePeerID + "." + sc.GetPinningServiceDID()) + rp, err := c.getPeer(cr.PinningNodePeerID+"."+sc.GetPinningServiceDID(), "") if err != nil { c.log.Error("Pinning Node not connected", "err", err) return nil, nil, err diff --git a/core/recover.go b/core/recover.go index 2ec20945..99b854bf 100644 --- a/core/recover.go +++ b/core/recover.go @@ -4,8 +4,6 @@ import ( "encoding/json" "fmt" "net/http" - "strconv" - "strings" "github.com/rubixchain/rubixgoplatform/block" "github.com/rubixchain/rubixgoplatform/contract" @@ -23,7 +21,6 @@ type SendRecoverRequest struct { func (c *Core) InitiateRecoverRBT(reqID string, req *model.RBTRecoverRequest) { br := c.initiateRecoverRBT(reqID, req) - fmt.Println("Request ID in InitiateRecoverRBT:", reqID) dc := c.GetWebReq(reqID) if dc == nil { c.log.Error("Failed to get did channels") @@ -34,7 +31,6 @@ func (c *Core) InitiateRecoverRBT(reqID string, req *model.RBTRecoverRequest) { func (c *Core) initiateRecoverRBT(reqID string, req *model.RBTRecoverRequest) *model.BasicResponse { - fmt.Println("Initiate Recover RBT Called ") resp := &model.BasicResponse{ Status: false, } @@ -44,44 +40,21 @@ func (c *Core) initiateRecoverRBT(reqID string, req *model.RBTRecoverRequest) *m return resp } - if !strings.Contains(req.Sender, ".") || !strings.Contains(req.PinningNode, ".") { - resp.Message = "Sender and Pinning Node address should be of the format PeerID.DID" - return resp - } - _, did, ok := util.ParseAddress(req.Sender) - if !ok { - resp.Message = "Invalid sender DID" - return resp - } - - pinningNodepeerid, pinningNodeDID, ok := util.ParseAddress(req.PinningNode) - fmt.Println("Pinning node:", pinningNodeDID, pinningNodepeerid) - if !ok { - resp.Message = "Invalid pinning DID" - return resp - } - - if req.TokenCount < MinTrnxAmt { - resp.Message = "Input transaction amount is less than minimum transaction amount" - return resp - } - - decimalPlaces := strconv.FormatFloat(req.TokenCount, 'f', -1, 64) - decimalPlacesStr := strings.Split(decimalPlaces, ".") - if len(decimalPlacesStr) == 2 && len(decimalPlacesStr[1]) > MaxDecimalPlaces { - c.log.Error("Transaction amount exceeds %d decimal places.\n", MaxDecimalPlaces) - resp.Message = fmt.Sprintf("Transaction amount exceeds %d decimal places.\n", MaxDecimalPlaces) + did := req.Sender + pinningNodeDID := req.PinningNode + pinningNodepeerid := c.w.GetPeerID(pinningNodeDID) + if pinningNodepeerid == "" { + c.log.Error("Peer ID not found", "did", pinningNodepeerid) + resp.Message = "invalid address, Peer ID not found" return resp } - dc, err := c.SetupDID(reqID, did) - fmt.Println("dc", dc) + _, err := c.SetupDID(reqID, did) if err != nil { resp.Message = "Failed to setup DID, " + err.Error() return resp } - p, err := c.getPeer(req.PinningNode) - fmt.Println("P in getPeer :", p) + p, err := c.getPeer(req.PinningNode, did) if err != nil { resp.Message = "Failed to get pinning peer, " + err.Error() return resp @@ -93,12 +66,12 @@ func (c *Core) initiateRecoverRBT(reqID string, req *model.RBTRecoverRequest) *m } else { signFunc = signModule.InitDIDLiteWithPassword(did, c.didDir, req.Password) } - //signFunc := signModule.InitDIDLiteWithPassword(did, c.didDir, "mypassword") - fmt.Println("c.didDIR", c.didDir) pvtSign, err := signFunc.PvtSign([]byte(did)) - fmt.Println("DID in initiateRecoverRBT", did) - fmt.Println("PVTSIGN in initiate Recover RBT", pvtSign) - fmt.Println("Error in initiateRecoverRBT", err) + if err != nil { + c.log.Error("Failed to sign while recovering RBT") + resp.Message = "Failed to sign, " + err.Error() + return resp + } signature := signModule.DIDSignature{ Pixels: []byte{}, Signature: pvtSign, @@ -110,20 +83,17 @@ func (c *Core) initiateRecoverRBT(reqID string, req *model.RBTRecoverRequest) *m var br model.BasicResponse err = p.SendJSONRequest("POST", APIRecoverPinnedRBT, nil, &sr, &br, true) if err != nil { - c.log.Error("Unable to send tokens to receiver", "err", err) - return nil + c.log.Error("Unable to send Recover Token Request to the pinned node", "err", err) + return &br + } + if !br.Status { + c.log.Error("Failed to recover RBT: ", br.Message) + return &br } - fmt.Println(br.Message) - fmt.Println(br.Result) - fmt.Println(br.Status) - - fmt.Printf("Type: %T, Value: %v\n", br.Result, br.Result) - - //tokenlist := br.Result retrieved, ok := br.Result.([]interface{}) if !ok { - fmt.Println("Failed to retrieve slice from interface") + c.log.Debug("Failed to retrieve slice from interface") } // Convert []interface{} to []TokenInfo var tokenInfos []contract.TokenInfo @@ -134,24 +104,9 @@ func (c *Core) initiateRecoverRBT(reqID string, req *model.RBTRecoverRequest) *m } } - // Print the retrieved data - fmt.Println("Successfully retrieved TokenInfo slice from interface:") - for i, tokenInfo := range tokenInfos { - fmt.Printf("TokenInfo %d: %+v\n", i, tokenInfo) - fmt.Printf("Block ID: %s\n", tokenInfo.BlockID) - fmt.Printf("Owner DID: %s\n", tokenInfo.OwnerDID) - fmt.Printf("Token: %s\n", tokenInfo.Token) - fmt.Printf("Token Type: %d\n", tokenInfo.TokenType) - fmt.Printf("Token Value: %f\n", tokenInfo.TokenValue) - + for _, tokenInfo := range tokenInfos { token := tokenInfo.Token tokenType := tokenInfo.TokenType - blockID := tokenInfo.BlockID - - // Perform your desired operation with the extracted fields - // For example, just print them - fmt.Printf("Token: %s, TokenType: %d, BlockID: %s\n", token, tokenType, blockID) - tr := TCBSyncRequest{ Token: token, TokenType: tokenType, @@ -168,13 +123,11 @@ func (c *Core) initiateRecoverRBT(reqID string, req *model.RBTRecoverRequest) *m c.log.Error("Failed to sync token chain block", "msg", trep.Message) } - fmt.Println("The response from the json request ", trep) for _, bb := range trep.TCBlock { blk := block.InitBlock(bb, nil) if blk == nil { c.log.Error("Failed to add token chain block, invalid block, sync failed", "err", err) } - fmt.Println("The block is ", blk) err = c.w.AddTokenBlock(token, blk) if err != nil { c.log.Error("Failed to add token chain block, syncing failed", "err", err) @@ -218,20 +171,17 @@ func (c *Core) initiateRecoverRBT(reqID string, req *model.RBTRecoverRequest) *m } func (c *Core) recoverPinnedToken(req *ensweb.Request) *ensweb.Result { - pinNodeDid := c.l.GetQuerry(req, "did") - fmt.Println("DID in recoverPinnedToken :", pinNodeDid) var sr SendRecoverRequest err := c.l.ParseJSON(req, &sr) crep := model.BasicResponse{ Status: false, } - fmt.Println("SR in recover Pinned Token :", sr) if err != nil { c.log.Error("Failed to parse json request", "err", err) crep.Message = "Failed to parse json request" return c.l.RenderJSON(req, &crep, http.StatusOK) } - p, err := c.getPeer(sr.Address) + p, err := c.getPeer(sr.Address, "") if err != nil { c.log.Error("failed to get peer", "err", err) crep.Message = "failed to get peer" @@ -240,15 +190,18 @@ func (c *Core) recoverPinnedToken(req *ensweb.Request) *ensweb.Result { defer p.Close() _, recoverNodeDID, _ := util.ParseAddress(sr.Address) recoveredTokens, err := c.w.GetAllPinnedTokens(recoverNodeDID) - fmt.Println("recoverDID in recoverPinnedToken :", recoverNodeDID) - fmt.Println("Recovered Tokens in the Pinned Node :", recoveredTokens) - fmt.Println("Err in recoveredTokens:", err) - + if err != nil { + c.log.Error("Failed to get the pinned tokens of did :", recoverNodeDID, "err", err) + crep.Message = "No tokens have been pinned for the DID :" + recoverNodeDID + return c.l.RenderJSON(req, &crep, http.StatusOK) + } signFunc := signModule.InitDIDLite(recoverNodeDID, c.didDir, nil) - fmt.Println("The directory in recoverPinnedToken", c.didDir) verified, err := signFunc.PvtVerify([]byte(recoverNodeDID), sr.Signature.Signature) - fmt.Println("Verified in recoverPinnedToken", verified) - fmt.Println("Err in recoverPinnedToken", err) + if !verified { + c.log.Error("Failed to verify signature of sender, Unable to recover tokens", "err", err) + crep.Message = "Failed to verify signature of sender, Unable to recover tokens" + return c.l.RenderJSON(req, &crep, http.StatusOK) + } tis := make([]contract.TokenInfo, 0) for i := range recoveredTokens { tts := "rbt" @@ -276,7 +229,6 @@ func (c *Core) recoverPinnedToken(req *ensweb.Request) *ensweb.Result { tis = append(tis, ti) } - fmt.Println("TIS is :", tis) crep.Status = true crep.Message = "Token Recovered Succesfully" crep.Result = tis @@ -285,29 +237,21 @@ func (c *Core) recoverPinnedToken(req *ensweb.Request) *ensweb.Result { func mapToTokenInfo(m map[string]interface{}) contract.TokenInfo { tokenType, err := m["tokenType"].(json.Number) - if err { - fmt.Println("The error in tokenType is :", err) + if !err { + fmt.Println("invalid type for tokenType :", err) } tokenTypeInt64, err1 := tokenType.Int64() if err1 != nil { - fmt.Println("The error in tokenTypeInt is :", err1) + fmt.Println("failed to convert tokenType to int64 :", err1) } - - fmt.Println("TokenType :", tokenType) - fmt.Println("TokenType Int64 :", tokenTypeInt64) - fmt.Println("Token Type int :", int(tokenTypeInt64)) - toknValue, err2 := m["tokenValue"].(json.Number) - if err2 { - fmt.Println("The error in tokenValue is :", err2) + if !err2 { + fmt.Println("invalid type for tokenValue :", err2) } tokenValueFloat64, err3 := toknValue.Float64() if err3 != nil { - fmt.Println("The error in tokenValueFloat64 is :", err3) + fmt.Println("failed to convert tokenValue to float64:", err3) } - fmt.Println("Token value :", toknValue) - fmt.Println("Token value float64", tokenValueFloat64) - return contract.TokenInfo{ Token: m["token"].(string), TokenType: int(tokenTypeInt64), diff --git a/core/token.go b/core/token.go index e70e714f..e11f08bf 100644 --- a/core/token.go +++ b/core/token.go @@ -112,6 +112,9 @@ func (c *Core) GetAccountInfo(did string) (model.DIDAccountInfo, error) { case wallet.TokenIsPledged: info.PledgedRBT = info.PledgedRBT + t.TokenValue info.PledgedRBT = floatPrecision(info.PledgedRBT, MaxDecimalPlaces) + case wallet.TokenIsPinnedAsService: + info.PinnedRBT = info.PinnedRBT + t.TokenValue + info.PinnedRBT = floatPrecision(info.PinnedRBT, MaxDecimalPlaces) } } return info, nil @@ -519,7 +522,9 @@ func (c *Core) UpdatePledgedTokenInfo(tokenstatehash string) error { func (c *Core) GetpinnedTokens(did string) ([]wallet.Token, error) { requiredTokens, err := c.w.GetAllPinnedTokens(did) - fmt.Println("err", err) - fmt.Println("The tokenlist received:", requiredTokens) + if err != nil { + c.log.Error("Error retrieving pinned tokens from database :", err) + return nil, err + } return requiredTokens, nil } diff --git a/core/transfer.go b/core/transfer.go index b86286ec..387772fd 100644 --- a/core/transfer.go +++ b/core/transfer.go @@ -10,7 +10,6 @@ import ( "github.com/rubixchain/rubixgoplatform/core/model" "github.com/rubixchain/rubixgoplatform/core/wallet" "github.com/rubixchain/rubixgoplatform/did" - "github.com/rubixchain/rubixgoplatform/util" "github.com/rubixchain/rubixgoplatform/wrapper/uuid" ) @@ -352,23 +351,15 @@ func (c *Core) initiatePinRBT(reqID string, req *model.RBTPinRequest) *model.Bas } if req.Sender == req.PinningNode { - resp.Message = "Sender and Pinning node cannot be same" + resp.Message = "Sender and receiver cannot be same" return resp } - - if !strings.Contains(req.Sender, ".") || !strings.Contains(req.PinningNode, ".") { - resp.Message = "Sender and Pinning Node address should be of the format PeerID.DID" - return resp - } - _, did, ok := util.ParseAddress(req.Sender) - if !ok { - resp.Message = "Invalid sender DID" - return resp - } - - pinningNodepeerid, pinningNodeDID, ok := util.ParseAddress(req.PinningNode) - if !ok { - resp.Message = "Invalid pinning DID" + did := req.Sender + pinningNodeDID := req.PinningNode + pinningNodepeerid := c.w.GetPeerID(pinningNodeDID) + if pinningNodepeerid == "" { + c.log.Error("Peer ID not found", "did", pinningNodeDID) + resp.Message = "invalid address, Peer ID not found" return resp } @@ -447,9 +438,9 @@ func (c *Core) initiatePinRBT(reqID string, req *model.RBTPinRequest) *model.Bas defer c.w.ReleaseTokens(tokensForTxn) for i := range tokensForTxn { - c.w.Pin(tokensForTxn[i].TokenID, wallet.PinningRole, did, "TID-Not Generated", req.Sender, req.PinningNode, tokensForTxn[i].TokenValue) //my comment : In this pin function the wallet.OwnerRole is changed to wallet.PinRole + c.w.Pin(tokensForTxn[i].TokenID, wallet.PinningRole, did, "TID-Not Generated", req.Sender, req.PinningNode, tokensForTxn[i].TokenValue) } - p, err := c.getPeer(req.PinningNode) + p, err := c.getPeer(req.PinningNode, did) if err != nil { resp.Message = "Failed to get pinning peer, " + err.Error() return resp From 812b27e7c229e988972d997ca936efc0691dcb60 Mon Sep 17 00:00:00 2001 From: Allen Iype P Cherian Date: Wed, 10 Jul 2024 18:56:49 +0530 Subject: [PATCH 110/129] Remove debug log --- block/block.go | 2 -- 1 file changed, 2 deletions(-) diff --git a/block/block.go b/block/block.go index 469624c6..2b246e27 100644 --- a/block/block.go +++ b/block/block.go @@ -129,14 +129,12 @@ func InitBlock(bb []byte, bm map[string]interface{}, opts ...BlockOption) *Block if b.bb == nil { err = b.blkEncode() if err != nil { - fmt.Println("failed to encode block", err.Error(), err) return nil } } if b.bm == nil { err = b.blkDecode() if err != nil { - fmt.Println("failed to decode block", err.Error(), err) return nil } } From afc9eaca6715183ec42ea459b724f90abcdd0187 Mon Sep 17 00:00:00 2001 From: Allen Iype P Cherian Date: Thu, 11 Jul 2024 17:54:31 +0530 Subject: [PATCH 111/129] Update cmd and api nomenclature --- command/command.go | 8 ++++---- server/tokens.go | 4 ++-- setup/setup.go | 4 ++-- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/command/command.go b/command/command.go index c855d188..e46e9b6b 100644 --- a/command/command.go +++ b/command/command.go @@ -88,8 +88,8 @@ const ( SelfTransferRBT string = "self-transfer-rbt" RunUnpledge string = "run-unpledge" UnpledgePOWPledgeTokens string = "unpledge-pow-pledge-tokens" - PinRBTCmd string = "pinrbt" - RecoverTokensCmd string = "recovertokens" + PinTokenCmd string = "pinToken" + RecoverTokensCmd string = "recoverToken" ) var commands = []string{VersionCmd, @@ -139,7 +139,7 @@ var commands = []string{VersionCmd, SelfTransferRBT, RunUnpledge, UnpledgePOWPledgeTokens, - PinRBTCmd, + PinTokenCmd, RecoverTokensCmd, } @@ -637,7 +637,7 @@ func Run(args []string) { cmd.RunUnpledge() case UnpledgePOWPledgeTokens: cmd.UnpledgePOWBasedPledgedTokens() - case PinRBTCmd: + case PinTokenCmd: cmd.PinRBT() case RecoverTokensCmd: cmd.RecoverTokens() diff --git a/server/tokens.go b/server/tokens.go index 5613f7c0..495c25e3 100644 --- a/server/tokens.go +++ b/server/tokens.go @@ -90,7 +90,7 @@ type RBTPinRequestSwaggoInput struct { // @Produce json // @Param input body RBTPinRequestSwaggoInput true "Intitate Pin RBT" // @Success 200 {object} model.BasicResponse -// @Router /api/initiate-pin-rbt [post] +// @Router /api/initiate-pin-token [post] func (s *Server) APIInitiatePinRBT(req *ensweb.Request) *ensweb.Result { var rbtReq model.RBTPinRequest @@ -126,7 +126,7 @@ type RBTRecoverRequestSwaggoInput struct { // @Produce json // @Param input body RBTRecoverRequestSwaggoInput true "Recover-RBT" // @Success 200 {object} model.BasicResponse -// @Router /api/api/recover-rbt [post] +// @Router /api/recover-token [post] func (s *Server) APIRecoverRBT(req *ensweb.Request) *ensweb.Result { var rbtReq model.RBTRecoverRequest diff --git a/setup/setup.go b/setup/setup.go index 23bca5fe..98e918c4 100644 --- a/setup/setup.go +++ b/setup/setup.go @@ -73,8 +73,8 @@ const ( APISelfTransfer string = "/api/initiate-self-transfer" APIRunUnpledge string = "/api/run-unpledge" APIUnpledgePOWPledgeTokens string = "/api/unpledge-pow-unpledge-tokens" - APIInitiatePinRBT string = "/api/initiate-pin-rbt" - APIRecoverRBT string = "/api/recover-rbt" + APIInitiatePinRBT string = "/api/initiate-pin-token" + APIRecoverRBT string = "/api/recover-token" ) // jwt.RegisteredClaims From 94c6a46df82d0b5e31842bc88cdb35c2d350a965 Mon Sep 17 00:00:00 2001 From: Allen Iype P Cherian Date: Thu, 11 Jul 2024 18:07:47 +0530 Subject: [PATCH 112/129] Add minor fix --- core/transfer.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/transfer.go b/core/transfer.go index 387772fd..128cad26 100644 --- a/core/transfer.go +++ b/core/transfer.go @@ -363,7 +363,7 @@ func (c *Core) initiatePinRBT(reqID string, req *model.RBTPinRequest) *model.Bas return resp } - if req.TokenCount < MinTrnxAmt { + if req.TokenCount < MinDecimalValue(MaxDecimalPlaces) { resp.Message = "Input transaction amount is less than minimum transaction amount" return resp } From 1c604dda5203bf25b329c5e4c642ce92aff5a53e Mon Sep 17 00:00:00 2001 From: Allen Iype P Cherian Date: Thu, 11 Jul 2024 20:00:45 +0530 Subject: [PATCH 113/129] Change error message --- core/transfer.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/core/transfer.go b/core/transfer.go index 128cad26..09a1e32e 100644 --- a/core/transfer.go +++ b/core/transfer.go @@ -389,8 +389,8 @@ func (c *Core) initiatePinRBT(reqID string, req *model.RBTPinRequest) *model.Bas return resp } else { if req.TokenCount > accountBalance.RBTAmount { - c.log.Error(fmt.Sprint("Insufficient balance, account balance is ", accountBalance.RBTAmount, " trnx value is ", req.TokenCount)) - resp.Message = fmt.Sprint("Insufficient balance, account balance is ", accountBalance.RBTAmount, " trnx value is ", req.TokenCount) + c.log.Error(fmt.Sprint("The requested amount not available for pinning ", req.TokenCount, " Token value available for pinning : ", accountBalance.RBTAmount)) + resp.Message = fmt.Sprint("The requested amount not available for pinning ", req.TokenCount, " Token value available for pinning : ", accountBalance.RBTAmount) return resp } } From ffcc77c19381f64ec143eda01504337b1a1ce82b Mon Sep 17 00:00:00 2001 From: Allen Iype P Cherian Date: Fri, 19 Jul 2024 10:17:58 +0530 Subject: [PATCH 114/129] Add fix: passing random uuid for signature --- core/core.go | 1 + core/quorum_initiator.go | 1 + core/recover.go | 29 +++++++++++++++++++++++++++-- go.mod | 1 + go.sum | 2 ++ 5 files changed, 32 insertions(+), 2 deletions(-) diff --git a/core/core.go b/core/core.go index 6f59c95c..eb95a07d 100644 --- a/core/core.go +++ b/core/core.go @@ -53,6 +53,7 @@ const ( APIAddUnpledgeDetails string = "/api/initiate-unpledge" APISelfTransfer string = "/api/self-transfer" APIRecoverPinnedRBT string = "/api/recover-pinned-rbt" + APIRequestSigningHash string = "/api/request-signing-hash" ) const ( diff --git a/core/quorum_initiator.go b/core/quorum_initiator.go index ae4bcc11..54015fb1 100644 --- a/core/quorum_initiator.go +++ b/core/quorum_initiator.go @@ -173,6 +173,7 @@ func (c *Core) QuroumSetup() { c.l.AddRoute(APIUpdateTokenHashDetails, "POST", c.updateTokenHashDetails) c.l.AddRoute(APIAddUnpledgeDetails, "POST", c.addUnpledgeDetails) c.l.AddRoute(APIRecoverPinnedRBT, "POST", c.recoverPinnedToken) + c.l.AddRoute(APIRequestSigningHash, "GET", c.requestSigningHash) if c.arbitaryMode { c.l.AddRoute(APIMapDIDArbitration, "POST", c.mapDIDArbitration) c.l.AddRoute(APICheckDIDArbitration, "GET", c.chekDIDArbitration) diff --git a/core/recover.go b/core/recover.go index 99b854bf..a4d79262 100644 --- a/core/recover.go +++ b/core/recover.go @@ -5,6 +5,7 @@ import ( "fmt" "net/http" + "github.com/google/uuid" "github.com/rubixchain/rubixgoplatform/block" "github.com/rubixchain/rubixgoplatform/contract" "github.com/rubixchain/rubixgoplatform/core/model" @@ -17,6 +18,7 @@ import ( type SendRecoverRequest struct { Address string `json:"peer_id"` Signature signModule.DIDSignature `json:"Signature"` + Hash string `json:"hash"` } func (c *Core) InitiateRecoverRBT(reqID string, req *model.RBTRecoverRequest) { @@ -60,13 +62,24 @@ func (c *Core) initiateRecoverRBT(reqID string, req *model.RBTRecoverRequest) *m return resp } defer p.Close() + var hashResponse model.BasicResponse + err = p.SendJSONRequest("GET", APIRequestSigningHash, nil, nil, &hashResponse, true) + if err != nil { + c.log.Error("Unable to send Recover Token Request to the pinned node", "err", err) + return &hashResponse + } + if !hashResponse.Status { + c.log.Error("Failed to get hash for signing from the pinned node") + return &hashResponse + } + hashForSign := hashResponse.Message var signFunc *signModule.DIDLite if req.Password == "" { signFunc = signModule.InitDIDLiteWithPassword(did, c.didDir, "mypassword") } else { signFunc = signModule.InitDIDLiteWithPassword(did, c.didDir, req.Password) } - pvtSign, err := signFunc.PvtSign([]byte(did)) + pvtSign, err := signFunc.PvtSign([]byte(hashForSign)) if err != nil { c.log.Error("Failed to sign while recovering RBT") resp.Message = "Failed to sign, " + err.Error() @@ -79,6 +92,7 @@ func (c *Core) initiateRecoverRBT(reqID string, req *model.RBTRecoverRequest) *m sr := SendRecoverRequest{ Address: req.Sender, Signature: signature, + Hash: hashForSign, } var br model.BasicResponse err = p.SendJSONRequest("POST", APIRecoverPinnedRBT, nil, &sr, &br, true) @@ -196,7 +210,7 @@ func (c *Core) recoverPinnedToken(req *ensweb.Request) *ensweb.Result { return c.l.RenderJSON(req, &crep, http.StatusOK) } signFunc := signModule.InitDIDLite(recoverNodeDID, c.didDir, nil) - verified, err := signFunc.PvtVerify([]byte(recoverNodeDID), sr.Signature.Signature) + verified, err := signFunc.PvtVerify([]byte(sr.Hash), sr.Signature.Signature) if !verified { c.log.Error("Failed to verify signature of sender, Unable to recover tokens", "err", err) crep.Message = "Failed to verify signature of sender, Unable to recover tokens" @@ -235,6 +249,17 @@ func (c *Core) recoverPinnedToken(req *ensweb.Request) *ensweb.Result { return c.l.RenderJSON(req, &crep, http.StatusOK) } +func (c *Core) requestSigningHash(req *ensweb.Request) *ensweb.Result { + c.log.Info("Request for Sign Hash received") + crep := model.BasicResponse{ + Status: false, + } + hashForSign := uuid.New().String() + crep.Status = true + crep.Message = hashForSign + return c.l.RenderJSON(req, &crep, http.StatusOK) +} + func mapToTokenInfo(m map[string]interface{}) contract.TokenInfo { tokenType, err := m["tokenType"].(json.Number) if !err { diff --git a/go.mod b/go.mod index 7d0ff4ba..a165f5e1 100644 --- a/go.mod +++ b/go.mod @@ -30,6 +30,7 @@ require ( github.com/gogo/protobuf v1.3.2 // indirect github.com/golang-jwt/jwt/v5 v5.0.0 github.com/golang/snappy v0.0.4 + github.com/google/uuid v1.6.0 github.com/gorilla/mux v1.8.0 github.com/ipfs/go-cid v0.2.0 // indirect github.com/jackc/pgx/v5 v5.3.1 // indirect diff --git a/go.sum b/go.sum index 37458085..a8fe684c 100644 --- a/go.sum +++ b/go.sum @@ -865,6 +865,8 @@ github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm4 github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= +github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/googleapis/enterprise-certificate-proxy v0.0.0-20220520183353-fd19c99a87aa/go.mod h1:17drOmN3MwGY7t0e+Ei9b45FFGA3fBs3x36SsCg1hq8= github.com/googleapis/enterprise-certificate-proxy v0.1.0/go.mod h1:17drOmN3MwGY7t0e+Ei9b45FFGA3fBs3x36SsCg1hq8= github.com/googleapis/enterprise-certificate-proxy v0.2.0/go.mod h1:8C0jb7/mgJe/9KK8Lm7X9ctZC2t60YyIpYEI16jx0Qg= From 91de45edb83ea2adb0a6cfe9956fc067e5632536 Mon Sep 17 00:00:00 2001 From: Allen Iype P Cherian Date: Fri, 19 Jul 2024 12:53:16 +0530 Subject: [PATCH 115/129] Fix: when rbtamount is not specified the entire tokens will be pinned --- core/transfer.go | 242 ++++++++++++++++++++++++++++++++++++++++--- core/wallet/token.go | 21 ++++ 2 files changed, 247 insertions(+), 16 deletions(-) diff --git a/core/transfer.go b/core/transfer.go index 09a1e32e..10623554 100644 --- a/core/transfer.go +++ b/core/transfer.go @@ -344,6 +344,205 @@ func (c *Core) InitiatePinRBT(reqID string, req *model.RBTPinRequest) { dc.OutChan <- br } +// func (c *Core) initiatePinRBT(reqID string, req *model.RBTPinRequest) *model.BasicResponse { +// st := time.Now() +// resp := &model.BasicResponse{ +// Status: false, +// } + +// if req.Sender == req.PinningNode { +// resp.Message = "Sender and receiver cannot be same" +// return resp +// } +// did := req.Sender +// pinningNodeDID := req.PinningNode +// pinningNodepeerid := c.w.GetPeerID(pinningNodeDID) +// if pinningNodepeerid == "" { +// c.log.Error("Peer ID not found", "did", pinningNodeDID) +// resp.Message = "invalid address, Peer ID not found" +// return resp +// } + +// if req.TokenCount == 0 { + +// } + +// if req.TokenCount < MinDecimalValue(MaxDecimalPlaces) { +// resp.Message = "Input transaction amount is less than minimum transaction amount" +// return resp +// } + +// decimalPlaces := strconv.FormatFloat(req.TokenCount, 'f', -1, 64) +// decimalPlacesStr := strings.Split(decimalPlaces, ".") +// if len(decimalPlacesStr) == 2 && len(decimalPlacesStr[1]) > MaxDecimalPlaces { +// c.log.Error("Transaction amount exceeds %d decimal places.\n", MaxDecimalPlaces) +// resp.Message = fmt.Sprintf("Transaction amount exceeds %d decimal places.\n", MaxDecimalPlaces) +// return resp +// } + +// dc, err := c.SetupDID(reqID, did) +// if err != nil { +// resp.Message = "Failed to setup DID, " + err.Error() +// return resp +// } + +// accountBalance, err := c.GetAccountInfo(did) +// if err != nil { +// c.log.Error("Failed to get tokens", "err", err) +// resp.Message = "Insufficient tokens or tokens are locked or " + err.Error() +// return resp +// } else { +// if req.TokenCount > accountBalance.RBTAmount { +// c.log.Error(fmt.Sprint("The requested amount not available for pinning ", req.TokenCount, " Token value available for pinning : ", accountBalance.RBTAmount)) +// resp.Message = fmt.Sprint("The requested amount not available for pinning ", req.TokenCount, " Token value available for pinning : ", accountBalance.RBTAmount) +// return resp +// } +// } + +// tokensForTxn := make([]wallet.Token, 0) + +// reqTokens, remainingAmount, err := c.GetRequiredTokens(did, req.TokenCount, PinningServiceMode) +// if err != nil { +// c.w.ReleaseTokens(reqTokens) +// c.log.Error("Failed to get tokens", "err", err) +// resp.Message = "Insufficient tokens or tokens are locked or " + err.Error() +// return resp +// } +// if len(reqTokens) != 0 { +// tokensForTxn = append(tokensForTxn, reqTokens...) +// } + +// // Get the required tokens from the DID bank +// // this method locks the token needs to be released or +// // removed once it done with the transfer +// if remainingAmount > 0 { +// wt, err := c.GetTokens(dc, did, remainingAmount, PinningServiceMode) +// if err != nil { +// c.log.Error("Failed to get tokens", "err", err) +// resp.Message = "Insufficient tokens or tokens are locked" +// return resp +// } +// if len(wt) != 0 { +// tokensForTxn = append(tokensForTxn, wt...) +// } +// } + +// var sumOfTokensForTxn float64 +// for _, tokenForTxn := range tokensForTxn { +// sumOfTokensForTxn = sumOfTokensForTxn + tokenForTxn.TokenValue +// sumOfTokensForTxn = floatPrecision(sumOfTokensForTxn, MaxDecimalPlaces) +// } + +// if sumOfTokensForTxn != req.TokenCount { +// c.log.Error(fmt.Sprint("Sum of Selected Tokens sum : ", sumOfTokensForTxn, " is not equal to trnx value : ", req.TokenCount)) +// resp.Message = fmt.Sprint("Sum of Selected Tokens sum : ", sumOfTokensForTxn, " is not equal to trnx value : ", req.TokenCount) +// return resp +// } +// // release the locked tokens before exit +// defer c.w.ReleaseTokens(tokensForTxn) + +// for i := range tokensForTxn { +// c.w.Pin(tokensForTxn[i].TokenID, wallet.PinningRole, did, "TID-Not Generated", req.Sender, req.PinningNode, tokensForTxn[i].TokenValue) +// } +// p, err := c.getPeer(req.PinningNode, did) +// if err != nil { +// resp.Message = "Failed to get pinning peer, " + err.Error() +// return resp +// } +// defer p.Close() + +// wta := make([]string, 0) +// for i := range tokensForTxn { +// wta = append(wta, tokensForTxn[i].TokenID) +// } + +// tis := make([]contract.TokenInfo, 0) + +// for i := range tokensForTxn { +// tts := "rbt" +// if tokensForTxn[i].TokenValue != 1 { +// tts = "part" +// } +// tt := c.TokenType(tts) +// blk := c.w.GetLatestTokenBlock(tokensForTxn[i].TokenID, tt) +// if blk == nil { +// c.log.Error("failed to get latest block, invalid token chain") +// resp.Message = "failed to get latest block, invalid token chain" +// return resp +// } +// bid, err := blk.GetBlockID(tokensForTxn[i].TokenID) +// if err != nil { +// c.log.Error("failed to get block id", "err", err) +// resp.Message = "failed to get block id, " + err.Error() +// return resp +// } +// //OwnerDID will be the same as the sender, so that ownership is not changed. +// ti := contract.TokenInfo{ +// Token: tokensForTxn[i].TokenID, +// TokenType: tt, +// TokenValue: tokensForTxn[i].TokenValue, +// OwnerDID: did, +// BlockID: bid, +// } + +// tis = append(tis, ti) +// } +// sct := &contract.ContractType{ +// Type: contract.SCRBTDirectType, +// PledgeMode: contract.POWPledgeMode, +// TotalRBTs: req.TokenCount, +// TransInfo: &contract.TransInfo{ +// SenderDID: did, +// PinningNodeDID: pinningNodeDID, +// Comment: req.Comment, +// TransTokens: tis, +// }, +// ReqID: reqID, +// } +// sc := contract.CreateNewContract(sct) +// err = sc.UpdateSignature(dc) +// if err != nil { +// c.log.Error(err.Error()) +// resp.Message = err.Error() +// return resp +// } +// cr := &ConensusRequest{ +// ReqID: uuid.New().String(), +// Type: req.Type, +// SenderPeerID: c.peerID, +// PinningNodePeerID: pinningNodepeerid, +// ContractBlock: sc.GetBlock(), +// Mode: PinningServiceMode, +// } +// td, _, err := c.initiateConsensus(cr, sc, dc) +// if err != nil { +// c.log.Error("Consensus failed", "err", err) +// resp.Message = "Consensus failed" + err.Error() +// return resp +// } +// et := time.Now() +// dif := et.Sub(st) +// td.Amount = req.TokenCount +// td.TotalTime = float64(dif.Milliseconds()) +// c.w.AddTransactionHistory(td) +// etrans := &ExplorerTrans{ +// TID: td.TransactionID, +// SenderDID: did, +// ReceiverDID: pinningNodeDID, +// Amount: req.TokenCount, +// TrasnType: req.Type, +// TokenIDs: wta, +// QuorumList: cr.QuorumList, +// TokenTime: float64(dif.Milliseconds()), +// } +// c.ec.ExplorerTransaction(etrans) +// c.log.Info("Pinning finished successfully", "duration", dif, " trnxid", td.TransactionID) +// resp.Status = true +// msg := fmt.Sprintf("Pinning finished successfully in %v with trnxid %v", dif, td.TransactionID) +// resp.Message = msg +// return resp +// } + func (c *Core) initiatePinRBT(reqID string, req *model.RBTPinRequest) *model.BasicResponse { st := time.Now() resp := &model.BasicResponse{ @@ -355,6 +554,11 @@ func (c *Core) initiatePinRBT(reqID string, req *model.RBTPinRequest) *model.Bas return resp } did := req.Sender + dc, err := c.SetupDID(reqID, did) + if err != nil { + resp.Message = "Failed to setup DID, " + err.Error() + return resp + } pinningNodeDID := req.PinningNode pinningNodepeerid := c.w.GetPeerID(pinningNodeDID) if pinningNodepeerid == "" { @@ -363,6 +567,24 @@ func (c *Core) initiatePinRBT(reqID string, req *model.RBTPinRequest) *model.Bas return resp } + // Handle the case where TokenCount is 0 + if req.TokenCount == 0 { + reqTokens, err := c.w.GetAllFreeToken(did) + if err != nil { + c.w.ReleaseTokens(reqTokens) + c.log.Error("Failed to get tokens", "err", err) + resp.Message = "Insufficient tokens or tokens are locked or " + err.Error() + return resp + } + + tokensForTxn := make([]wallet.Token, 0) + if len(reqTokens) != 0 { + tokensForTxn = append(tokensForTxn, reqTokens...) + } + + return c.completePinning(st, reqID, req, did, pinningNodeDID, pinningNodepeerid, tokensForTxn, resp, dc) + } + if req.TokenCount < MinDecimalValue(MaxDecimalPlaces) { resp.Message = "Input transaction amount is less than minimum transaction amount" return resp @@ -375,13 +597,6 @@ func (c *Core) initiatePinRBT(reqID string, req *model.RBTPinRequest) *model.Bas resp.Message = fmt.Sprintf("Transaction amount exceeds %d decimal places.\n", MaxDecimalPlaces) return resp } - - dc, err := c.SetupDID(reqID, did) - if err != nil { - resp.Message = "Failed to setup DID, " + err.Error() - return resp - } - accountBalance, err := c.GetAccountInfo(did) if err != nil { c.log.Error("Failed to get tokens", "err", err) @@ -408,9 +623,6 @@ func (c *Core) initiatePinRBT(reqID string, req *model.RBTPinRequest) *model.Bas tokensForTxn = append(tokensForTxn, reqTokens...) } - // Get the required tokens from the DID bank - // this method locks the token needs to be released or - // removed once it done with the transfer if remainingAmount > 0 { wt, err := c.GetTokens(dc, did, remainingAmount, PinningServiceMode) if err != nil { @@ -423,17 +635,15 @@ func (c *Core) initiatePinRBT(reqID string, req *model.RBTPinRequest) *model.Bas } } + return c.completePinning(st, reqID, req, did, pinningNodeDID, pinningNodepeerid, tokensForTxn, resp, dc) +} + +func (c *Core) completePinning(st time.Time, reqID string, req *model.RBTPinRequest, did, pinningNodeDID, pinningNodepeerid string, tokensForTxn []wallet.Token, resp *model.BasicResponse, dc did.DIDCrypto) *model.BasicResponse { var sumOfTokensForTxn float64 for _, tokenForTxn := range tokensForTxn { sumOfTokensForTxn = sumOfTokensForTxn + tokenForTxn.TokenValue sumOfTokensForTxn = floatPrecision(sumOfTokensForTxn, MaxDecimalPlaces) } - - if sumOfTokensForTxn != req.TokenCount { - c.log.Error(fmt.Sprint("Sum of Selected Tokens sum : ", sumOfTokensForTxn, " is not equal to trnx value : ", req.TokenCount)) - resp.Message = fmt.Sprint("Sum of Selected Tokens sum : ", sumOfTokensForTxn, " is not equal to trnx value : ", req.TokenCount) - return resp - } // release the locked tokens before exit defer c.w.ReleaseTokens(tokensForTxn) diff --git a/core/wallet/token.go b/core/wallet/token.go index b3cbadd2..4d5f144e 100644 --- a/core/wallet/token.go +++ b/core/wallet/token.go @@ -262,6 +262,27 @@ func (w *Wallet) GetToken(token string, token_Status int) (*Token, error) { return &t, nil } +func (w *Wallet) GetAllFreeToken(did string) ([]Token, error) { + w.l.Lock() + defer w.l.Unlock() + var t []Token + err := w.s.Read(TokenStorage, &t, "did=? AND token_status=?", did, TokenIsFree) + if err != nil { + w.log.Error("Failed to get tokens", "err", err) + return nil, err + } + for i := range t { + t[i].TokenStatus = TokenIsLocked + err = w.s.Update(TokenStorage, &t[i], "did=? AND token_id=?", did, t[i].TokenID) + if err != nil { + w.log.Error("Failed to update token status", "err", err) + return nil, err + } + } + //::TODO:: Part Tokens + return t, nil +} + func (w *Wallet) ReadToken(token string) (*Token, error) { w.l.Lock() defer w.l.Unlock() From 5373cd057a436079130246d26cd9a33389d44594 Mon Sep 17 00:00:00 2001 From: Allen Iype P Cherian Date: Fri, 19 Jul 2024 12:54:31 +0530 Subject: [PATCH 116/129] Remove comment --- core/transfer.go | 199 ----------------------------------------------- 1 file changed, 199 deletions(-) diff --git a/core/transfer.go b/core/transfer.go index 10623554..48d24eba 100644 --- a/core/transfer.go +++ b/core/transfer.go @@ -344,205 +344,6 @@ func (c *Core) InitiatePinRBT(reqID string, req *model.RBTPinRequest) { dc.OutChan <- br } -// func (c *Core) initiatePinRBT(reqID string, req *model.RBTPinRequest) *model.BasicResponse { -// st := time.Now() -// resp := &model.BasicResponse{ -// Status: false, -// } - -// if req.Sender == req.PinningNode { -// resp.Message = "Sender and receiver cannot be same" -// return resp -// } -// did := req.Sender -// pinningNodeDID := req.PinningNode -// pinningNodepeerid := c.w.GetPeerID(pinningNodeDID) -// if pinningNodepeerid == "" { -// c.log.Error("Peer ID not found", "did", pinningNodeDID) -// resp.Message = "invalid address, Peer ID not found" -// return resp -// } - -// if req.TokenCount == 0 { - -// } - -// if req.TokenCount < MinDecimalValue(MaxDecimalPlaces) { -// resp.Message = "Input transaction amount is less than minimum transaction amount" -// return resp -// } - -// decimalPlaces := strconv.FormatFloat(req.TokenCount, 'f', -1, 64) -// decimalPlacesStr := strings.Split(decimalPlaces, ".") -// if len(decimalPlacesStr) == 2 && len(decimalPlacesStr[1]) > MaxDecimalPlaces { -// c.log.Error("Transaction amount exceeds %d decimal places.\n", MaxDecimalPlaces) -// resp.Message = fmt.Sprintf("Transaction amount exceeds %d decimal places.\n", MaxDecimalPlaces) -// return resp -// } - -// dc, err := c.SetupDID(reqID, did) -// if err != nil { -// resp.Message = "Failed to setup DID, " + err.Error() -// return resp -// } - -// accountBalance, err := c.GetAccountInfo(did) -// if err != nil { -// c.log.Error("Failed to get tokens", "err", err) -// resp.Message = "Insufficient tokens or tokens are locked or " + err.Error() -// return resp -// } else { -// if req.TokenCount > accountBalance.RBTAmount { -// c.log.Error(fmt.Sprint("The requested amount not available for pinning ", req.TokenCount, " Token value available for pinning : ", accountBalance.RBTAmount)) -// resp.Message = fmt.Sprint("The requested amount not available for pinning ", req.TokenCount, " Token value available for pinning : ", accountBalance.RBTAmount) -// return resp -// } -// } - -// tokensForTxn := make([]wallet.Token, 0) - -// reqTokens, remainingAmount, err := c.GetRequiredTokens(did, req.TokenCount, PinningServiceMode) -// if err != nil { -// c.w.ReleaseTokens(reqTokens) -// c.log.Error("Failed to get tokens", "err", err) -// resp.Message = "Insufficient tokens or tokens are locked or " + err.Error() -// return resp -// } -// if len(reqTokens) != 0 { -// tokensForTxn = append(tokensForTxn, reqTokens...) -// } - -// // Get the required tokens from the DID bank -// // this method locks the token needs to be released or -// // removed once it done with the transfer -// if remainingAmount > 0 { -// wt, err := c.GetTokens(dc, did, remainingAmount, PinningServiceMode) -// if err != nil { -// c.log.Error("Failed to get tokens", "err", err) -// resp.Message = "Insufficient tokens or tokens are locked" -// return resp -// } -// if len(wt) != 0 { -// tokensForTxn = append(tokensForTxn, wt...) -// } -// } - -// var sumOfTokensForTxn float64 -// for _, tokenForTxn := range tokensForTxn { -// sumOfTokensForTxn = sumOfTokensForTxn + tokenForTxn.TokenValue -// sumOfTokensForTxn = floatPrecision(sumOfTokensForTxn, MaxDecimalPlaces) -// } - -// if sumOfTokensForTxn != req.TokenCount { -// c.log.Error(fmt.Sprint("Sum of Selected Tokens sum : ", sumOfTokensForTxn, " is not equal to trnx value : ", req.TokenCount)) -// resp.Message = fmt.Sprint("Sum of Selected Tokens sum : ", sumOfTokensForTxn, " is not equal to trnx value : ", req.TokenCount) -// return resp -// } -// // release the locked tokens before exit -// defer c.w.ReleaseTokens(tokensForTxn) - -// for i := range tokensForTxn { -// c.w.Pin(tokensForTxn[i].TokenID, wallet.PinningRole, did, "TID-Not Generated", req.Sender, req.PinningNode, tokensForTxn[i].TokenValue) -// } -// p, err := c.getPeer(req.PinningNode, did) -// if err != nil { -// resp.Message = "Failed to get pinning peer, " + err.Error() -// return resp -// } -// defer p.Close() - -// wta := make([]string, 0) -// for i := range tokensForTxn { -// wta = append(wta, tokensForTxn[i].TokenID) -// } - -// tis := make([]contract.TokenInfo, 0) - -// for i := range tokensForTxn { -// tts := "rbt" -// if tokensForTxn[i].TokenValue != 1 { -// tts = "part" -// } -// tt := c.TokenType(tts) -// blk := c.w.GetLatestTokenBlock(tokensForTxn[i].TokenID, tt) -// if blk == nil { -// c.log.Error("failed to get latest block, invalid token chain") -// resp.Message = "failed to get latest block, invalid token chain" -// return resp -// } -// bid, err := blk.GetBlockID(tokensForTxn[i].TokenID) -// if err != nil { -// c.log.Error("failed to get block id", "err", err) -// resp.Message = "failed to get block id, " + err.Error() -// return resp -// } -// //OwnerDID will be the same as the sender, so that ownership is not changed. -// ti := contract.TokenInfo{ -// Token: tokensForTxn[i].TokenID, -// TokenType: tt, -// TokenValue: tokensForTxn[i].TokenValue, -// OwnerDID: did, -// BlockID: bid, -// } - -// tis = append(tis, ti) -// } -// sct := &contract.ContractType{ -// Type: contract.SCRBTDirectType, -// PledgeMode: contract.POWPledgeMode, -// TotalRBTs: req.TokenCount, -// TransInfo: &contract.TransInfo{ -// SenderDID: did, -// PinningNodeDID: pinningNodeDID, -// Comment: req.Comment, -// TransTokens: tis, -// }, -// ReqID: reqID, -// } -// sc := contract.CreateNewContract(sct) -// err = sc.UpdateSignature(dc) -// if err != nil { -// c.log.Error(err.Error()) -// resp.Message = err.Error() -// return resp -// } -// cr := &ConensusRequest{ -// ReqID: uuid.New().String(), -// Type: req.Type, -// SenderPeerID: c.peerID, -// PinningNodePeerID: pinningNodepeerid, -// ContractBlock: sc.GetBlock(), -// Mode: PinningServiceMode, -// } -// td, _, err := c.initiateConsensus(cr, sc, dc) -// if err != nil { -// c.log.Error("Consensus failed", "err", err) -// resp.Message = "Consensus failed" + err.Error() -// return resp -// } -// et := time.Now() -// dif := et.Sub(st) -// td.Amount = req.TokenCount -// td.TotalTime = float64(dif.Milliseconds()) -// c.w.AddTransactionHistory(td) -// etrans := &ExplorerTrans{ -// TID: td.TransactionID, -// SenderDID: did, -// ReceiverDID: pinningNodeDID, -// Amount: req.TokenCount, -// TrasnType: req.Type, -// TokenIDs: wta, -// QuorumList: cr.QuorumList, -// TokenTime: float64(dif.Milliseconds()), -// } -// c.ec.ExplorerTransaction(etrans) -// c.log.Info("Pinning finished successfully", "duration", dif, " trnxid", td.TransactionID) -// resp.Status = true -// msg := fmt.Sprintf("Pinning finished successfully in %v with trnxid %v", dif, td.TransactionID) -// resp.Message = msg -// return resp -// } - func (c *Core) initiatePinRBT(reqID string, req *model.RBTPinRequest) *model.BasicResponse { st := time.Now() resp := &model.BasicResponse{ From 4580632b7cc0c15a60f82c8fc4a068507bfbf4ae Mon Sep 17 00:00:00 2001 From: Allen Iype P Cherian Date: Mon, 22 Jul 2024 11:06:29 +0530 Subject: [PATCH 117/129] Increase test script wait time to 80s --- tests/node/commands.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/node/commands.py b/tests/node/commands.py index 90ff2ff2..b0c07bd1 100644 --- a/tests/node/commands.py +++ b/tests/node/commands.py @@ -65,8 +65,8 @@ def cmd_run_rubix_servers(node_name, server_port_idx): if code != 0: raise Exception("Error occurred while run the command: " + cmd_string) - print("Waiting for 40 seconds before checking if its running....") - time.sleep(40) + print("Waiting for 80 seconds before checking if its running....") + time.sleep(80) try: check_if_nodes_is_running(server_port_idx) except Exception as e: From 74f9cc3c1d916a13da5b26d05e0bb90d86fd70c5 Mon Sep 17 00:00:00 2001 From: Allen Iype P Cherian Date: Tue, 23 Jul 2024 17:19:57 +0530 Subject: [PATCH 118/129] Fix: Changes respective to rebase --- core/quorum_initiator.go | 113 ++++++++++++++++++++++++++++++++++++--- core/quorum_recv.go | 6 +-- core/transfer.go | 6 +-- core/wallet/token.go | 29 ++++------ 4 files changed, 122 insertions(+), 32 deletions(-) diff --git a/core/quorum_initiator.go b/core/quorum_initiator.go index 54015fb1..5f5ac90d 100644 --- a/core/quorum_initiator.go +++ b/core/quorum_initiator.go @@ -567,7 +567,7 @@ func (c *Core) initiateConsensus(cr *ConensusRequest, sc *contract.Contract, dc c.log.Error("Pledge finlaity not achieved", "err", err) return nil, nil, pledgeFinalityError } - err = c.w.TokensTransferred(sc.GetSenderDID(), ti, nb, rp.IsLocal()) + err = c.w.TokensTransferred(sc.GetSenderDID(), ti, nb, rp.IsLocal(), sr.PinningServiceMode) if err != nil { c.log.Error("Failed to transfer tokens", "err", err) return nil, nil, err @@ -620,17 +620,112 @@ func (c *Core) initiateConsensus(cr *ConensusRequest, sc *contract.Contract, dc QuorumList: cr.QuorumList, PinningServiceMode: true, } + //fetching quorums' info from PeerDIDTable to share with the receiver + for _, qrm := range sr.QuorumList { + //fetch peer id & did of the quorum + qpid, qdid, ok := util.ParseAddress(qrm) + if !ok { + c.log.Error("could not parse quorum address:", qrm) + } + if qpid == "" { + qpid = c.w.GetPeerID(qdid) + } + + var qrmInfo QuorumDIDPeerMap + //fetch did type of the quorum + qDidType, err := c.w.GetPeerDIDType(qdid) + if err != nil { + c.log.Error("could not fetch did type for quorum:", qdid, "error", err) + } + if qDidType == -1 { + c.log.Info("did type is empty for quorum:", qdid, "connecting & fetching from quorum") + didtype_, msg, err := c.GetPeerdidType_fromPeer(qpid, qdid, dc.GetDID()) + if err != nil { + c.log.Error("error", err, "msg", msg) + qrmInfo.DIDType = nil + } else { + qDidType = didtype_ + qrmInfo.DIDType = &qDidType + } + } else { + qrmInfo.DIDType = &qDidType + } + //add quorum details to the data to be shared + qrmInfo.DID = qdid + qrmInfo.PeerID = qpid + sr.QuorumInfo = append(sr.QuorumInfo, qrmInfo) + } var br model.BasicResponse err = rp.SendJSONRequest("POST", APISendReceiverToken, nil, &sr, &br, true) if err != nil { c.log.Error("Unable to send tokens to receiver", "err", err) return nil, nil, err } + + if strings.Contains(br.Message, "failed to sync tokenchain") { + tokenPrefix := "Token: " + issueTypePrefix := "issueType: " + + // Find the starting indexes of pt and issueType values + ptStart := strings.Index(br.Message, tokenPrefix) + len(tokenPrefix) + issueTypeStart := strings.Index(br.Message, issueTypePrefix) + len(issueTypePrefix) + + // Extracting the substrings from the message + token := br.Message[ptStart : strings.Index(br.Message[ptStart:], ",")+ptStart] + issueType := br.Message[issueTypeStart:] + + c.log.Debug("String: token is ", token, " issuetype is ", issueType) + issueTypeInt, err1 := strconv.Atoi(issueType) + if err1 != nil { + errMsg := fmt.Sprintf("Consensus failed due to token chain sync issue, issueType string conversion, err %v", err1) + c.log.Error(errMsg) + return nil, nil, fmt.Errorf(errMsg) + } + c.log.Debug("issue type in int is ", issueTypeInt) + syncIssueTokenDetails, err2 := c.w.ReadToken(token) + if err2 != nil { + errMsg := fmt.Sprintf("Consensus failed due to tokenchain sync issue, err %v", err2) + c.log.Error(errMsg) + return nil, nil, fmt.Errorf(errMsg) + } + c.log.Debug("sync issue token details ", syncIssueTokenDetails) + if issueTypeInt == TokenChainNotSynced { + syncIssueTokenDetails.TokenStatus = wallet.TokenChainSyncIssue + c.log.Debug("sync issue token details status updated", syncIssueTokenDetails) + c.w.UpdateToken(syncIssueTokenDetails) + return nil, nil, errors.New(br.Message) + } + } + if !br.Status { - c.log.Error("Unable to send tokens to receiver", "msg", br.Message) - return nil, nil, fmt.Errorf("unable to send tokens to receiver, " + br.Message) + c.log.Error("Unable to send tokens to pinning node", "msg", br.Message) + return nil, nil, fmt.Errorf("unable to send tokens to pinning node, " + br.Message) + } + + // br.Result will contain the new token state after sending tokens to receiver as a response to APISendReceiverToken + newtokenhashresult, ok := br.Result.([]interface{}) + if !ok { + c.log.Error("Type assertion to string failed") + return nil, nil, fmt.Errorf("Type assertion to string failed") + } + var newtokenhashes []string + for i, newTokenHash := range newtokenhashresult { + statehash, ok := newTokenHash.(string) + if !ok { + c.log.Error("Type assertion to string failed at index", i) + return nil, nil, fmt.Errorf("Type assertion to string failed at index", i) + } + newtokenhashes = append(newtokenhashes, statehash) + } + + //trigger pledge finality to the quorum and also adding the new tokenstate hash details for transferred tokens to quorum + pledgeFinalityError := c.quorumPledgeFinality(cr, nb, newtokenhashes, tid) + if pledgeFinalityError != nil { + c.log.Error("Pledge finlaity not achieved", "err", err) + return nil, nil, pledgeFinalityError } - err = c.w.TokensTransferred(sc.GetSenderDID(), ti, nb, rp.IsLocal(), true) + + err = c.w.TokensTransferred(sc.GetSenderDID(), ti, nb, rp.IsLocal(), sr.PinningServiceMode) if err != nil { c.log.Error("Failed to transfer tokens", "err", err) return nil, nil, err @@ -647,7 +742,7 @@ func (c *Core) initiateConsensus(cr *ConensusRequest, sc *contract.Contract, dc return nil, nil, err } - td := wallet.TransactionDetails{ + td := model.TransactionDetails{ TransactionID: tid, TransactionType: nb.GetTransType(), BlockID: nbid, @@ -657,6 +752,12 @@ func (c *Core) initiateConsensus(cr *ConensusRequest, sc *contract.Contract, dc Comment: sc.GetComment(), DateTime: time.Now(), Status: true, + Epoch: int64(cr.TransactionEpoch), + } + err = c.initiateUnpledgingProcess(cr, td.TransactionID, td.Epoch) + if err != nil { + c.log.Error("Failed to store transactiond details with quorum ", "err", err) + return nil, nil, err } return &td, pl, nil case SelfTransferMode: @@ -700,7 +801,7 @@ func (c *Core) initiateConsensus(cr *ConensusRequest, sc *contract.Contract, dc } // Self update for self transfer tokens - updatedTokenHashes, err := c.updateReceiverToken(selfAddress, "", ti, nb.GetBlock(), cr.QuorumList, quorumInfo, cr.TransactionEpoch) + updatedTokenHashes, err := c.updateReceiverToken(selfAddress, "", ti, nb.GetBlock(), cr.QuorumList, quorumInfo, cr.TransactionEpoch, false) if err != nil { errMsg := fmt.Errorf("failed while update of self transfer tokens, err: %v", err) c.log.Error(errMsg.Error()) diff --git a/core/quorum_recv.go b/core/quorum_recv.go index e93c58b0..1f66e670 100644 --- a/core/quorum_recv.go +++ b/core/quorum_recv.go @@ -633,7 +633,7 @@ func (c *Core) reqPledgeToken(req *ensweb.Request) *ensweb.Result { func (c *Core) updateReceiverToken( senderAddress string, receiverAddress string, tokenInfo []contract.TokenInfo, tokenChainBlock []byte, - quorumList []string, quorumInfo []QuorumDIDPeerMap, transactionEpoch int, + quorumList []string, quorumInfo []QuorumDIDPeerMap, transactionEpoch int, pinningServiceMode bool, ) ([]string, error) { var receiverPeerId string = "" var receiverDID string = "" @@ -747,7 +747,7 @@ func (c *Core) updateReceiverToken( c.log.Debug("Token", tokenStateCheckResult[i].Token, "Message", tokenStateCheckResult[i].Message) } - updatedTokenStateHashes, err := c.w.TokensReceived(receiverDID, tokenInfo, b, senderPeerId, receiverPeerId, c.ipfs, sr.PinningServiceMode) + updatedTokenStateHashes, err := c.w.TokensReceived(receiverDID, tokenInfo, b, senderPeerId, receiverPeerId, pinningServiceMode, c.ipfs) if err != nil { return nil, fmt.Errorf("Failed to update token status, error: %v", err) } @@ -803,7 +803,6 @@ func (c *Core) updateReceiverTokenHandle(req *ensweb.Request) *ensweb.Result { } receiverAddress := c.peerID + "." + did - updatedtokenhashes, err := c.updateReceiverToken( sr.Address, receiverAddress, @@ -812,6 +811,7 @@ func (c *Core) updateReceiverTokenHandle(req *ensweb.Request) *ensweb.Result { sr.QuorumList, sr.QuorumInfo, sr.TransactionEpoch, + sr.PinningServiceMode, ) if err != nil { c.log.Error(err.Error()) diff --git a/core/transfer.go b/core/transfer.go index 48d24eba..f209a601 100644 --- a/core/transfer.go +++ b/core/transfer.go @@ -48,7 +48,7 @@ func gatherTokensForTransaction(c *Core, req *model.RBTTransferRequest, dc did.D } } - reqTokens, remainingAmount, err := c.GetRequiredTokens(senderDID, req.TokenCount) + reqTokens, remainingAmount, err := c.GetRequiredTokens(senderDID, req.TokenCount, RBTTransferMode) if err != nil { c.w.ReleaseTokens(reqTokens) return nil, fmt.Errorf("insufficient tokens or tokens are locked or %v", err.Error()) @@ -62,7 +62,7 @@ func gatherTokensForTransaction(c *Core, req *model.RBTTransferRequest, dc did.D // this method locks the token needs to be released or // removed once it done with the transfer if remainingAmount > 0 { - wt, err := c.GetTokens(dc, senderDID, remainingAmount) + wt, err := c.GetTokens(dc, senderDID, remainingAmount, RBTTransferMode) if err != nil { return nil, fmt.Errorf("insufficient tokens or tokens are locked or %v", err.Error()) } @@ -496,7 +496,7 @@ func (c *Core) completePinning(st time.Time, reqID string, req *model.RBTPinRequ } sct := &contract.ContractType{ Type: contract.SCRBTDirectType, - PledgeMode: contract.POWPledgeMode, + PledgeMode: contract.PeriodicPledgeMode, TotalRBTs: req.TokenCount, TransInfo: &contract.TransInfo{ SenderDID: did, diff --git a/core/wallet/token.go b/core/wallet/token.go index 4d5f144e..e3f0acbf 100644 --- a/core/wallet/token.go +++ b/core/wallet/token.go @@ -464,9 +464,8 @@ func (w *Wallet) TokensReceived(did string, ti []contract.TokenInfo, b *block.Bl if err != nil || t.TokenID == "" { // Token doesn't exist, proceed to handle it dir := util.GetRandString() - err := util.CreateDir(dir) - if err != nil { - w.log.Error("Faled to create directory", "err", err) + if err := util.CreateDir(dir); err != nil { + w.log.Error("Failed to create directory", "err", err) return nil, err } defer os.RemoveAll(dir) @@ -484,21 +483,17 @@ func (w *Wallet) TokensReceived(did string, ti []contract.TokenInfo, b *block.Bl parentTokenID, _, _ = gb.GetParentDetials(tokenInfo.Token) } - tokenId := ti[i].Token - // Create new token entry t = Token{ - TokenID: tokenId, - TokenValue: ti[i].TokenValue, - ParentTokenID: pt, TokenID: tokenInfo.Token, TokenValue: tokenInfo.TokenValue, ParentTokenID: parentTokenID, DID: tokenInfo.OwnerDID, } - t.TokenStateHash = tokenHashMap[tokenId] + t.TokenStateHash = tokenHashMap[tokenInfo.Token] - if err := w.s.Write(TokenStorage, &t); err != nil { + err = w.s.Write(TokenStorage, &t) + if err != nil { return nil, err } } @@ -515,26 +510,20 @@ func (w *Wallet) TokensReceived(did string, ti []contract.TokenInfo, b *block.Bl // Update token status t.DID = ownerdid t.TokenStatus = tokenStatus - t.TransactionID = b.GetTid() - t.TokenStateHash = tokenHashMap[t.TokenID] - if err := w.s.Update(TokenStorage, &t, "token_id=?", tokenInfo.Token); err != nil { + err = w.s.Update(TokenStorage, &t, "token_id=?", tokenInfo.Token) + if err != nil { return nil, err } senderAddress := senderPeerId + "." + b.GetSenderDID() receiverAddress := receiverPeerId + "." + b.GetReceiverDID() - - // Pin the token + //Pinnig the whole tokens and pat tokens ok, err := w.Pin(tokenInfo.Token, role, did, b.GetTid(), senderAddress, receiverAddress, tokenInfo.TokenValue) if err != nil { return nil, err } if !ok { - msg := "failed to pin token" - if pinningServiceMode { - msg = "failed to pin token as Service" - } - return fmt.Errorf(msg) + return nil, fmt.Errorf("failed to pin token") } } // for i := range pt { From 17fb83a0d0f63bd28a24dd2a039bce649f7200c3 Mon Sep 17 00:00:00 2001 From: Arnab Ghose Date: Wed, 24 Jul 2024 10:05:33 +0530 Subject: [PATCH 119/129] fixed the update of transaction_id in TokensTable --- core/transfer.go | 4 +++- core/unpledge.go | 9 +++++---- core/wallet/token.go | 3 ++- 3 files changed, 10 insertions(+), 6 deletions(-) diff --git a/core/transfer.go b/core/transfer.go index f209a601..718018db 100644 --- a/core/transfer.go +++ b/core/transfer.go @@ -113,7 +113,9 @@ func gatherTokensForTransaction(c *Core, req *model.RBTTransferRequest, dc did.D } } - c.log.Debug("Tokens acquired for self transfer") + if len(tokensForTransfer) > 0 { + c.log.Debug("Tokens acquired for self transfer") + } return tokensForTransfer, nil } } diff --git a/core/unpledge.go b/core/unpledge.go index db44514d..3001797e 100644 --- a/core/unpledge.go +++ b/core/unpledge.go @@ -50,9 +50,6 @@ func (c *Core) ForceUnpledgePOWBasedPledgedTokens() error { return nil } - - - func (c *Core) InititateUnpledgeProcess() (string, error) { c.log.Info("Unpledging process has started...") var totalUnpledgeAmount float64 = 0.0 @@ -136,7 +133,11 @@ func (c *Core) InititateUnpledgeProcess() (string, error) { } } - return fmt.Sprintf("Unpledging of pledged tokens was successful, Total Unpledge Amount: %v RBT", totalUnpledgeAmount), nil + if totalUnpledgeAmount > 0 { + return fmt.Sprintf("Unpledging of pledged tokens was successful, Total Unpledge Amount: %v RBT", totalUnpledgeAmount), nil + } else { + return "No tokens present to unpledge", nil + } } func unpledgeToken(c *Core, pledgeToken string, pledgeTokenType int, quorumDID string) (pledgeID string, unpledgeId string, err error) { diff --git a/core/wallet/token.go b/core/wallet/token.go index e3f0acbf..56286758 100644 --- a/core/wallet/token.go +++ b/core/wallet/token.go @@ -490,7 +490,6 @@ func (w *Wallet) TokensReceived(did string, ti []contract.TokenInfo, b *block.Bl ParentTokenID: parentTokenID, DID: tokenInfo.OwnerDID, } - t.TokenStateHash = tokenHashMap[tokenInfo.Token] err = w.s.Write(TokenStorage, &t) if err != nil { @@ -510,6 +509,8 @@ func (w *Wallet) TokensReceived(did string, ti []contract.TokenInfo, b *block.Bl // Update token status t.DID = ownerdid t.TokenStatus = tokenStatus + t.TransactionID = b.GetTid() + t.TokenStateHash = tokenHashMap[tokenInfo.Token] err = w.s.Update(TokenStorage, &t, "token_id=?", tokenInfo.Token) if err != nil { From 3cdc4ee498b6358f4f3018a53a663e65ef28fc4e Mon Sep 17 00:00:00 2001 From: Arnab Ghose Date: Tue, 30 Jul 2024 14:20:25 +0530 Subject: [PATCH 120/129] fixed assignment for `rpeerid` variable --- core/transfer.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/transfer.go b/core/transfer.go index 718018db..622cce2d 100644 --- a/core/transfer.go +++ b/core/transfer.go @@ -217,7 +217,7 @@ func (c *Core) initiateRBTTransfer(reqID string, req *model.RBTTransferRequest) // Get the receiver & do sanity check var rpeerid string = "" if !isSelfRBTTransfer { - rpeerid := c.w.GetPeerID(receiverdid) + rpeerid = c.w.GetPeerID(receiverdid) if rpeerid == "" { c.log.Error("Peer ID not found", "did", receiverdid) resp.Message = "invalid address, Peer ID not found" From b4be393b402c8787eed3ca4c4f2fd9673761dbbc Mon Sep 17 00:00:00 2001 From: Ashita Gupta Date: Tue, 30 Jul 2024 14:35:17 +0530 Subject: [PATCH 121/129] minor fixes --- core/transfer.go | 2 +- server/smart_contract.go | 5 ++--- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/core/transfer.go b/core/transfer.go index 718018db..622cce2d 100644 --- a/core/transfer.go +++ b/core/transfer.go @@ -217,7 +217,7 @@ func (c *Core) initiateRBTTransfer(reqID string, req *model.RBTTransferRequest) // Get the receiver & do sanity check var rpeerid string = "" if !isSelfRBTTransfer { - rpeerid := c.w.GetPeerID(receiverdid) + rpeerid = c.w.GetPeerID(receiverdid) if rpeerid == "" { c.log.Error("Peer ID not found", "did", receiverdid) resp.Message = "invalid address, Peer ID not found" diff --git a/server/smart_contract.go b/server/smart_contract.go index b4c531e2..d27147aa 100644 --- a/server/smart_contract.go +++ b/server/smart_contract.go @@ -407,9 +407,8 @@ func (s *Server) APIExecuteSmartContract(req *ensweb.Request) *ensweb.Result { s.log.Error("Invalid smart contract token") return s.BasicResponse(req, false, "Invalid smart contract token", nil) } - - is_alphanumeric = regexp.MustCompile(`^[a-zA-Z0-9]*$`).MatchString(executeReq.ExecutorAddress) - if !strings.HasPrefix(executeReq.ExecutorAddress, "bafybmi") || len(executeReq.ExecutorAddress) != 59 || !is_alphanumeric { + is_alphanumeric = regexp.MustCompile(`^[a-zA-Z0-9]*$`).MatchString(did) + if !strings.HasPrefix(did, "bafybmi") || len(did) != 59 || !is_alphanumeric { s.log.Error("Invalid executer DID") return s.BasicResponse(req, false, "Invalid executer DID", nil) } From 331a88cb73b46f6200079bc510d789eb4b18ba25 Mon Sep 17 00:00:00 2001 From: Arnab Ghose Date: Wed, 31 Jul 2024 10:11:22 +0530 Subject: [PATCH 122/129] tests: added generate swarm key inside tests/test_swarm_key dir to exclude from being added to the Git stagging area --- .gitignore | 5 +---- tests/fixtures/testswarm_linux.key | 3 --- tests/fixtures/testswarm_mac.key | 3 --- tests/fixtures/testswarm_windows.key | 3 --- tests/run.py | 9 +++++++-- 5 files changed, 8 insertions(+), 15 deletions(-) delete mode 100644 tests/fixtures/testswarm_linux.key delete mode 100644 tests/fixtures/testswarm_mac.key delete mode 100644 tests/fixtures/testswarm_windows.key diff --git a/.gitignore b/.gitignore index cbaf76d2..1c45b91b 100644 --- a/.gitignore +++ b/.gitignore @@ -28,10 +28,7 @@ linux/ mac/ windows/ dist/ - -testswarm_linux.key -testswarm_windows.key -testswarm_mac.key +test_swarm_key/ # used for testing purpose !node_registry.json diff --git a/tests/fixtures/testswarm_linux.key b/tests/fixtures/testswarm_linux.key deleted file mode 100644 index 534e7acb..00000000 --- a/tests/fixtures/testswarm_linux.key +++ /dev/null @@ -1,3 +0,0 @@ -/key/swarm/psk/1.0.0/ -/base16/ -278b9a199c43fa84178920bd9f5cbcd69e933ddf02a8f69e47a3ea5a1705513f \ No newline at end of file diff --git a/tests/fixtures/testswarm_mac.key b/tests/fixtures/testswarm_mac.key deleted file mode 100644 index 7490ebe9..00000000 --- a/tests/fixtures/testswarm_mac.key +++ /dev/null @@ -1,3 +0,0 @@ -/key/swarm/psk/1.0.0/ -/base16/ -e105d6caa191dc76ff553d36d094fafb2ad1c646000a52ebc89b488e17f61f92 \ No newline at end of file diff --git a/tests/fixtures/testswarm_windows.key b/tests/fixtures/testswarm_windows.key deleted file mode 100644 index 7490ebe9..00000000 --- a/tests/fixtures/testswarm_windows.key +++ /dev/null @@ -1,3 +0,0 @@ -/key/swarm/psk/1.0.0/ -/base16/ -e105d6caa191dc76ff553d36d094fafb2ad1c646000a52ebc89b488e17f61f92 \ No newline at end of file diff --git a/tests/run.py b/tests/run.py index 94f60874..8cddd9d5 100644 --- a/tests/run.py +++ b/tests/run.py @@ -24,7 +24,11 @@ def generate_ipfs_swarm_key(build_name): output = "/key/swarm/psk/1.0.0/\n/base16/\n" + binascii.hexlify(key).decode() - filename = f"./fixtures/testswarm_{build_name}.key" + directory = "./test_swarm_key" + filename = f"{directory}/testswarm_{build_name}.key" + + if not os.path.exists(directory): + os.makedirs(directory) with open(filename, "w") as file: file.write(output) @@ -121,7 +125,8 @@ def copy_fixtures_to_build_dir(build_directory): raise FileNotFoundError(f"Copy operation for didimage.png.file failed. Destination file not found: {image_file_dest}") # Copy testswarm.key - swarmkey_src = os.path.join(fixtures_directory, f"testswarm_{build_directory}.key") + swarm_key_dir = os.path.join("tests", "test_swarm_key") + swarmkey_src = os.path.join(swarm_key_dir, f"testswarm_{build_directory}.key") swarmkey_dest = os.path.join(build_directory, f"testswarm.key") shutil.copyfile(swarmkey_src, swarmkey_dest) From 064d1dc416604f3ef60a5f7cd5cd96d5acc90142 Mon Sep 17 00:00:00 2001 From: Vaishnav CH Date: Wed, 31 Jul 2024 13:21:36 +0530 Subject: [PATCH 123/129] Change in `maxDecimalPlaces` and string formatting --- command/did.go | 3 ++- core/core.go | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/command/did.go b/command/did.go index f424ef25..79715525 100644 --- a/command/did.go +++ b/command/did.go @@ -10,6 +10,7 @@ import ( "strings" "time" + "github.com/rubixchain/rubixgoplatform/core" "github.com/rubixchain/rubixgoplatform/core/model" "github.com/rubixchain/rubixgoplatform/crypto" "github.com/rubixchain/rubixgoplatform/did" @@ -371,6 +372,6 @@ func (cmd *Command) GetAccountInfo() { cmd.log.Error("Failed to get account info", "message", info.Message) } else { cmd.log.Info("Successfully got the account information") - fmt.Printf("RBT : %10.5f, Locked RBT : %10.5f, Pledged RBT : %10.5f, Pinned RBT : %10.5f\n", info.AccountInfo[0].RBTAmount, info.AccountInfo[0].LockedRBT, info.AccountInfo[0].PledgedRBT, info.AccountInfo[0].PinnedRBT) + fmt.Printf("RBT : %10.*f, Locked RBT : %10.*f, Pledged RBT : %10.*f, Pinned RBT : %10.*f\n", core.MaxDecimalPlaces, info.AccountInfo[0].RBTAmount, core.MaxDecimalPlaces, info.AccountInfo[0].LockedRBT, core.MaxDecimalPlaces, info.AccountInfo[0].PledgedRBT, core.MaxDecimalPlaces, info.AccountInfo[0].PinnedRBT) } } diff --git a/core/core.go b/core/core.go index eb95a07d..4299af8d 100644 --- a/core/core.go +++ b/core/core.go @@ -64,7 +64,7 @@ const ( MainNetDir string = "MainNet" TestNetDir string = "TestNet" TestNetDIDDir string = "TestNetDID/" - MaxDecimalPlaces int = 5 + MaxDecimalPlaces int = 3 ) const ( From 56d4be3fdff848f2580fcc442869f48b9e5a98bf Mon Sep 17 00:00:00 2001 From: Arnab Ghose Date: Wed, 31 Jul 2024 15:30:46 +0530 Subject: [PATCH 124/129] fixed the self transfer command by changing the TransferRBT `client` package call to SelfTransferRBT call --- command/transfer.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/command/transfer.go b/command/transfer.go index 5693c173..525b8cea 100644 --- a/command/transfer.go +++ b/command/transfer.go @@ -97,7 +97,7 @@ func (cmd *Command) SelfTransferRBT() { Type: cmd.transType, } - br, err := cmd.c.TransferRBT(&rt) + br, err := cmd.c.SelfTransferRBT(&rt) if err != nil { cmd.log.Error("Failed to self RBT transfer", "err", err) return From f75ab3df43a54ac19b2949dca38668a9cf677aab Mon Sep 17 00:00:00 2001 From: Arnab Ghose Date: Thu, 1 Aug 2024 09:11:57 +0530 Subject: [PATCH 125/129] fixed precision to MaxDecimalPlaces (currently 3) for RBT token value --- core/transfer.go | 4 ++-- core/uitl.go | 4 ++-- server/tokens.go | 6 +++--- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/core/transfer.go b/core/transfer.go index 622cce2d..b9de45fa 100644 --- a/core/transfer.go +++ b/core/transfer.go @@ -260,7 +260,7 @@ func (c *Core) initiateRBTTransfer(reqID string, req *model.RBTTransferRequest) ti := contract.TokenInfo{ Token: tokensForTxn[i].TokenID, TokenType: tt, - TokenValue: tokensForTxn[i].TokenValue, + TokenValue: floatPrecision(tokensForTxn[i].TokenValue, MaxDecimalPlaces), OwnerDID: tokensForTxn[i].DID, BlockID: bid, } @@ -489,7 +489,7 @@ func (c *Core) completePinning(st time.Time, reqID string, req *model.RBTPinRequ ti := contract.TokenInfo{ Token: tokensForTxn[i].TokenID, TokenType: tt, - TokenValue: tokensForTxn[i].TokenValue, + TokenValue: floatPrecision(tokensForTxn[i].TokenValue, MaxDecimalPlaces), OwnerDID: did, BlockID: bid, } diff --git a/core/uitl.go b/core/uitl.go index 60244dfd..b1543527 100644 --- a/core/uitl.go +++ b/core/uitl.go @@ -24,10 +24,10 @@ func (c *Core) getTotalAmountFromTokenHashes(tokenHashes []string) (float64, err return 0.0, fmt.Errorf("getTotalAmountFromTokenHashes: failed to read token %v, err: %v", tokenHash, err) } - totalAmount += walletToken.TokenValue + totalAmount += floatPrecision(walletToken.TokenValue, MaxDecimalPlaces) } - return totalAmount, nil + return floatPrecision(totalAmount, MaxDecimalPlaces), nil } func (c *Core) RACPartTokenType() int { diff --git a/server/tokens.go b/server/tokens.go index 1d50bb9b..622eb502 100644 --- a/server/tokens.go +++ b/server/tokens.go @@ -90,9 +90,9 @@ func (s *Server) APIInitiateRBTTransfer(req *ensweb.Request) *ensweb.Result { s.log.Error("Invalid sender or receiver DID") return s.BasicResponse(req, false, "Invalid sender or receiver DID", nil) } - if rbtReq.TokenCount < 0.00001 { - s.log.Error("Invalid RBT amount. RBT amount should be atlease 0.00001") - return s.BasicResponse(req, false, "Invalid RBT amount. RBT amount should be atlease 0.00001", nil) + if rbtReq.TokenCount < 0.001 { + s.log.Error("Invalid RBT amount. RBT amount should be atlease 0.001") + return s.BasicResponse(req, false, "Invalid RBT amount. RBT amount should be atlease 0.001", nil) } if rbtReq.Type < 1 || rbtReq.Type > 2 { s.log.Error("Invalid trans type. TransType should be 1 or 2") From c4a2a6fac0a77e2379323557529067b9e4e5cb3a Mon Sep 17 00:00:00 2001 From: Arnab Ghose Date: Thu, 1 Aug 2024 09:16:36 +0530 Subject: [PATCH 126/129] fixed the validation to check RBT amount minimum value from 0.00001 to 0.001 --- command/smartContract.go | 4 ++-- command/transfer.go | 4 ++-- server/smart_contract.go | 6 +++--- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/command/smartContract.go b/command/smartContract.go index 61184f8e..cb73c760 100644 --- a/command/smartContract.go +++ b/command/smartContract.go @@ -196,8 +196,8 @@ func (cmd *Command) deploySmartcontract() { cmd.log.Error("Invalid deployer DID") return } - if cmd.rbtAmount < 0.00001 { - cmd.log.Error("Invalid RBT amount. Minimum RBT amount should be 0.00001") + if cmd.rbtAmount < 0.001 { + cmd.log.Error("Invalid RBT amount. Minimum RBT amount should be 0.001") return } if cmd.transType < 1 || cmd.transType > 2 { diff --git a/command/transfer.go b/command/transfer.go index 525b8cea..17340acf 100644 --- a/command/transfer.go +++ b/command/transfer.go @@ -37,8 +37,8 @@ func (cmd *Command) TransferRBT() { cmd.log.Error("Invalid sender or receiver DID") return } - if cmd.rbtAmount < 0.00001 { - cmd.log.Error("Invalid RBT amount. RBT amount should be atlease 0.00001") + if cmd.rbtAmount < 0.001 { + cmd.log.Error("Invalid RBT amount. RBT amount should be atlease 0.001") return } if cmd.transType < 1 || cmd.transType > 2 { diff --git a/server/smart_contract.go b/server/smart_contract.go index d27147aa..6618e26e 100644 --- a/server/smart_contract.go +++ b/server/smart_contract.go @@ -69,9 +69,9 @@ func (s *Server) APIDeploySmartContract(req *ensweb.Request) *ensweb.Result { return s.BasicResponse(req, false, "Invalid input", nil) } - if deployReq.RBTAmount < 0.00001 { - s.log.Error("Invalid RBT amount. Minimum RBT amount should be 0.00001") - return s.BasicResponse(req, false, "Invalid RBT amount. Minimum RBT amount should be 0.00001", nil) + if deployReq.RBTAmount < 0.001 { + s.log.Error("Invalid RBT amount. Minimum RBT amount should be 0.001") + return s.BasicResponse(req, false, "Invalid RBT amount. Minimum RBT amount should be 0.001", nil) } if deployReq.QuorumType < 1 || deployReq.QuorumType > 2 { s.log.Error("Invalid quorum type") From 431f0bf90e6ef11ebbd6e84b0729024b42a9324e Mon Sep 17 00:00:00 2001 From: Arnab Ghose Date: Thu, 1 Aug 2024 09:37:12 +0530 Subject: [PATCH 127/129] bump version from 0.0.17 to 0.0.18 --- command/command.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/command/command.go b/command/command.go index e46e9b6b..8af7b9bd 100644 --- a/command/command.go +++ b/command/command.go @@ -33,7 +33,7 @@ const ( ) const ( - version string = "0.0.17" + version string = "0.0.18" ) const ( VersionCmd string = "-v" From 3c5de7f65dc0694faf410a51ecf19eb29d2ad61f Mon Sep 17 00:00:00 2001 From: Arnab Ghose Date: Thu, 1 Aug 2024 12:07:17 +0530 Subject: [PATCH 128/129] fixed swagger input by removing input params which were not necessary Self Transfer API by defining a seperate struct for user input; assigned reciever to be same as sender in the Self Transfer handle func --- docs/docs.go | 15 +++++++++++++-- docs/swagger.json | 15 +++++++++++++-- docs/swagger.yaml | 11 +++++++++-- server/self_transfer.go | 15 +++++++++------ 4 files changed, 44 insertions(+), 12 deletions(-) diff --git a/docs/docs.go b/docs/docs.go index c9dfb017..fa1af5ab 100644 --- a/docs/docs.go +++ b/docs/docs.go @@ -751,12 +751,12 @@ const docTemplate = `{ "operationId": "initiate-self-transfer", "parameters": [ { - "description": "Intitate RBT transfer", + "description": "Intitate Self RBT transfer", "name": "input", "in": "body", "required": true, "schema": { - "$ref": "#/definitions/server.RBTTransferRequestSwaggoInput" + "$ref": "#/definitions/server.RBTSelfTransferRequestSwaggoInput" } } ], @@ -1161,6 +1161,17 @@ const docTemplate = `{ } } }, + "server.RBTSelfTransferRequestSwaggoInput": { + "type": "object", + "properties": { + "sender": { + "type": "string" + }, + "type": { + "type": "integer" + } + } + }, "server.RBTTransferRequestSwaggoInput": { "type": "object", "properties": { diff --git a/docs/swagger.json b/docs/swagger.json index 28a44c64..dd821c9a 100644 --- a/docs/swagger.json +++ b/docs/swagger.json @@ -743,12 +743,12 @@ "operationId": "initiate-self-transfer", "parameters": [ { - "description": "Intitate RBT transfer", + "description": "Intitate Self RBT transfer", "name": "input", "in": "body", "required": true, "schema": { - "$ref": "#/definitions/server.RBTTransferRequestSwaggoInput" + "$ref": "#/definitions/server.RBTSelfTransferRequestSwaggoInput" } } ], @@ -1153,6 +1153,17 @@ } } }, + "server.RBTSelfTransferRequestSwaggoInput": { + "type": "object", + "properties": { + "sender": { + "type": "string" + }, + "type": { + "type": "integer" + } + } + }, "server.RBTTransferRequestSwaggoInput": { "type": "object", "properties": { diff --git a/docs/swagger.yaml b/docs/swagger.yaml index 07e77ffc..11c7796a 100644 --- a/docs/swagger.yaml +++ b/docs/swagger.yaml @@ -138,6 +138,13 @@ definitions: smartContractToken: type: string type: object + server.RBTSelfTransferRequestSwaggoInput: + properties: + sender: + type: string + type: + type: integer + type: object server.RBTTransferRequestSwaggoInput: properties: comment: @@ -656,12 +663,12 @@ paths: description: This API will initiate self RBT transfer for a specific DID operationId: initiate-self-transfer parameters: - - description: Intitate RBT transfer + - description: Intitate Self RBT transfer in: body name: input required: true schema: - $ref: '#/definitions/server.RBTTransferRequestSwaggoInput' + $ref: '#/definitions/server.RBTSelfTransferRequestSwaggoInput' produces: - application/json responses: diff --git a/server/self_transfer.go b/server/self_transfer.go index 3b9effd2..ad275e21 100644 --- a/server/self_transfer.go +++ b/server/self_transfer.go @@ -5,13 +5,18 @@ import ( "github.com/rubixchain/rubixgoplatform/core/model" ) +type RBTSelfTransferRequestSwaggoInput struct { + Sender string `json:"sender"` + Type int `json:"type"` +} + // @Summary Initiate Self Transfer // @Description This API will initiate self RBT transfer for a specific DID // @Tags Account // @ID initiate-self-transfer // @Accept json // @Produce json -// @Param input body RBTTransferRequestSwaggoInput true "Intitate RBT transfer" +// @Param input body RBTSelfTransferRequestSwaggoInput true "Intitate Self RBT transfer" // @Success 200 {object} model.BasicResponse // @Router /api/initiate-self-transfer [post] func (s *Server) SelfTransferHandle(req *ensweb.Request) *ensweb.Result { @@ -22,16 +27,14 @@ func (s *Server) SelfTransferHandle(req *ensweb.Request) *ensweb.Result { } senderDID := selfTransferReq.Sender - receiverDID := selfTransferReq.Receiver - - if receiverDID != "" && senderDID != receiverDID { - return s.BasicResponse(req, false, "Sender and Receiver must be same in case of self transfer", nil) - } + if !s.validateDIDAccess(req, senderDID) { return s.BasicResponse(req, false, "DID does not have an access", nil) } + // Make receiver to be same as sender for Self Transfer + selfTransferReq.Receiver = selfTransferReq.Sender s.c.AddWebReq(req) go s.c.InitiateRBTTransfer(req.ID, &selfTransferReq) From c5679bb1f8eaa203a6fe2bb32f2c2c1bf9d2e427 Mon Sep 17 00:00:00 2001 From: Arnab Ghose Date: Thu, 1 Aug 2024 13:16:02 +0530 Subject: [PATCH 129/129] fixed swagger doc for token pinning and recover --- docs/docs.go | 107 ++++++++++++++++++++++++++++++++++++++++++++++ docs/swagger.json | 107 ++++++++++++++++++++++++++++++++++++++++++++++ docs/swagger.yaml | 71 ++++++++++++++++++++++++++++++ server/tokens.go | 16 +++---- 4 files changed, 292 insertions(+), 9 deletions(-) diff --git a/docs/docs.go b/docs/docs.go index fa1af5ab..7b993c97 100644 --- a/docs/docs.go +++ b/docs/docs.go @@ -700,6 +700,41 @@ const docTemplate = `{ } } }, + "/api/initiate-pin-token": { + "post": { + "description": "This API will pin token in the Pinning node on behalf of the sender", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "Account" + ], + "summary": "Initiate Pin Token", + "operationId": "initiate-pin-token", + "parameters": [ + { + "description": "Intitate Pin Token", + "name": "input", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/server.RBTPinRequestSwaggoInput" + } + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/model.BasicResponse" + } + } + } + } + }, "/api/initiate-rbt-transfer": { "post": { "description": "This API will initiate RBT transfer to the specified dID", @@ -770,6 +805,41 @@ const docTemplate = `{ } } }, + "/api/recover-token": { + "post": { + "description": "This API will recover token and tokenchain from the Pinning node to the node which has pinned the token", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "Account" + ], + "summary": "Recover Token and Tokenchain from the pinning node", + "operationId": "recover-token", + "parameters": [ + { + "description": "Recover-Token", + "name": "input", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/server.RBTRecoverRequestSwaggoInput" + } + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/model.BasicResponse" + } + } + } + } + }, "/api/register-callback-url": { "post": { "description": "This API will register call back url for when updated come for smart contract token", @@ -1161,6 +1231,43 @@ const docTemplate = `{ } } }, + "server.RBTPinRequestSwaggoInput": { + "type": "object", + "properties": { + "comment": { + "type": "string" + }, + "pinningNode": { + "type": "string" + }, + "sender": { + "type": "string" + }, + "tokenCOunt": { + "type": "number" + }, + "type": { + "type": "integer" + } + } + }, + "server.RBTRecoverRequestSwaggoInput": { + "type": "object", + "properties": { + "password": { + "type": "string" + }, + "pinningNode": { + "type": "string" + }, + "sender": { + "type": "string" + }, + "tokenCOunt": { + "type": "number" + } + } + }, "server.RBTSelfTransferRequestSwaggoInput": { "type": "object", "properties": { diff --git a/docs/swagger.json b/docs/swagger.json index dd821c9a..34e58bee 100644 --- a/docs/swagger.json +++ b/docs/swagger.json @@ -692,6 +692,41 @@ } } }, + "/api/initiate-pin-token": { + "post": { + "description": "This API will pin token in the Pinning node on behalf of the sender", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "Account" + ], + "summary": "Initiate Pin Token", + "operationId": "initiate-pin-token", + "parameters": [ + { + "description": "Intitate Pin Token", + "name": "input", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/server.RBTPinRequestSwaggoInput" + } + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/model.BasicResponse" + } + } + } + } + }, "/api/initiate-rbt-transfer": { "post": { "description": "This API will initiate RBT transfer to the specified dID", @@ -762,6 +797,41 @@ } } }, + "/api/recover-token": { + "post": { + "description": "This API will recover token and tokenchain from the Pinning node to the node which has pinned the token", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "Account" + ], + "summary": "Recover Token and Tokenchain from the pinning node", + "operationId": "recover-token", + "parameters": [ + { + "description": "Recover-Token", + "name": "input", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/server.RBTRecoverRequestSwaggoInput" + } + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/model.BasicResponse" + } + } + } + } + }, "/api/register-callback-url": { "post": { "description": "This API will register call back url for when updated come for smart contract token", @@ -1153,6 +1223,43 @@ } } }, + "server.RBTPinRequestSwaggoInput": { + "type": "object", + "properties": { + "comment": { + "type": "string" + }, + "pinningNode": { + "type": "string" + }, + "sender": { + "type": "string" + }, + "tokenCOunt": { + "type": "number" + }, + "type": { + "type": "integer" + } + } + }, + "server.RBTRecoverRequestSwaggoInput": { + "type": "object", + "properties": { + "password": { + "type": "string" + }, + "pinningNode": { + "type": "string" + }, + "sender": { + "type": "string" + }, + "tokenCOunt": { + "type": "number" + } + } + }, "server.RBTSelfTransferRequestSwaggoInput": { "type": "object", "properties": { diff --git a/docs/swagger.yaml b/docs/swagger.yaml index 11c7796a..899cedf9 100644 --- a/docs/swagger.yaml +++ b/docs/swagger.yaml @@ -138,6 +138,30 @@ definitions: smartContractToken: type: string type: object + server.RBTPinRequestSwaggoInput: + properties: + comment: + type: string + pinningNode: + type: string + sender: + type: string + tokenCOunt: + type: number + type: + type: integer + type: object + server.RBTRecoverRequestSwaggoInput: + properties: + password: + type: string + pinningNode: + type: string + sender: + type: string + tokenCOunt: + type: number + type: object server.RBTSelfTransferRequestSwaggoInput: properties: sender: @@ -633,6 +657,29 @@ paths: summary: Get ALL NFTs tags: - NFT + /api/initiate-pin-token: + post: + consumes: + - application/json + description: This API will pin token in the Pinning node on behalf of the sender + operationId: initiate-pin-token + parameters: + - description: Intitate Pin Token + in: body + name: input + required: true + schema: + $ref: '#/definitions/server.RBTPinRequestSwaggoInput' + produces: + - application/json + responses: + "200": + description: OK + schema: + $ref: '#/definitions/model.BasicResponse' + summary: Initiate Pin Token + tags: + - Account /api/initiate-rbt-transfer: post: consumes: @@ -679,6 +726,30 @@ paths: summary: Initiate Self Transfer tags: - Account + /api/recover-token: + post: + consumes: + - application/json + description: This API will recover token and tokenchain from the Pinning node + to the node which has pinned the token + operationId: recover-token + parameters: + - description: Recover-Token + in: body + name: input + required: true + schema: + $ref: '#/definitions/server.RBTRecoverRequestSwaggoInput' + produces: + - application/json + responses: + "200": + description: OK + schema: + $ref: '#/definitions/model.BasicResponse' + summary: Recover Token and Tokenchain from the pinning node + tags: + - Account /api/register-callback-url: post: consumes: diff --git a/server/tokens.go b/server/tokens.go index 622eb502..cf513cea 100644 --- a/server/tokens.go +++ b/server/tokens.go @@ -117,16 +117,15 @@ type RBTPinRequestSwaggoInput struct { } // ShowAccount godoc -// @Summary Initiate Pin RBT -// @Description This API will pin rbt in the Pinning node on behalf of the sender +// @Summary Initiate Pin Token +// @Description This API will pin token in the Pinning node on behalf of the sender // @Tags Account -// @ID initiate-pin-rbt +// @ID initiate-pin-token // @Accept json // @Produce json -// @Param input body RBTPinRequestSwaggoInput true "Intitate Pin RBT" +// @Param input body RBTPinRequestSwaggoInput true "Intitate Pin Token" // @Success 200 {object} model.BasicResponse // @Router /api/initiate-pin-token [post] - func (s *Server) APIInitiatePinRBT(req *ensweb.Request) *ensweb.Result { var rbtReq model.RBTPinRequest err := s.ParseJSON(req, &rbtReq) @@ -153,16 +152,15 @@ type RBTRecoverRequestSwaggoInput struct { } // ShowAccount godoc -// @Summary Recover RBT Token and Tokenchain from the pinning node +// @Summary Recover Token and Tokenchain from the pinning node // @Description This API will recover token and tokenchain from the Pinning node to the node which has pinned the token // @Tags Account -// @ID recover-rbt +// @ID recover-token // @Accept json // @Produce json -// @Param input body RBTRecoverRequestSwaggoInput true "Recover-RBT" +// @Param input body RBTRecoverRequestSwaggoInput true "Recover-Token" // @Success 200 {object} model.BasicResponse // @Router /api/recover-token [post] - func (s *Server) APIRecoverRBT(req *ensweb.Request) *ensweb.Result { var rbtReq model.RBTRecoverRequest err := s.ParseJSON(req, &rbtReq)