Skip to content

Commit

Permalink
Merge pull request #148 from rubixchain/ft/quorum-setup-check
Browse files Browse the repository at this point in the history
Add feature: Alternate quorum selection
  • Loading branch information
gklps authored May 3, 2024
2 parents 876b418 + 617ff4e commit b23a852
Show file tree
Hide file tree
Showing 16 changed files with 199 additions and 16 deletions.
18 changes: 18 additions & 0 deletions client/ping.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package client

import (
"strings"
"time"

"github.com/rubixchain/rubixgoplatform/core/model"
Expand All @@ -17,3 +18,20 @@ func (c *Client) Ping(peerID string) (string, bool) {
}
return rm.Message, rm.Status
}

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)
if err != nil {
return "Check quorum failed, " + err.Error(), false
}
return rm.Message, rm.Status
}
8 changes: 7 additions & 1 deletion command/command.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ const (
)

const (
version string = "0.0.15"
version string = "0.0.16"
)
const (
VersionCmd string = "-v"
Expand Down Expand Up @@ -77,6 +77,7 @@ const (
GetTokenBlock string = "gettokenblock"
GetSmartContractData string = "getsmartcontractdata"
ReleaseAllLockedTokensCmd string = "releaseAllLockedTokens"
CheckQuorumStatusCmd string = "checkQuorumStatus"
)

var commands = []string{VersionCmd,
Expand Down Expand Up @@ -121,6 +122,7 @@ var commands = []string{VersionCmd,
DumpSmartContractTokenChainCmd,
GetTokenBlock,
GetSmartContractData,
CheckQuorumStatusCmd,
}
var commandsHelp = []string{"To get tool version",
"To get help",
Expand Down Expand Up @@ -237,6 +239,7 @@ type Command struct {
smartContractData string
executorAddr string
latest bool
quorumAddr string
}

func showVersion() {
Expand Down Expand Up @@ -428,6 +431,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")

if len(os.Args) < 2 {
fmt.Println("Invalid Command")
Expand Down Expand Up @@ -570,6 +574,8 @@ func Run(args []string) {
cmd.executeSmartcontract()
case ReleaseAllLockedTokensCmd:
cmd.releaseAllLockedTokens()
case CheckQuorumStatusCmd:
cmd.checkQuorumStatus()
default:
cmd.log.Error("Invalid command")
}
Expand Down
2 changes: 1 addition & 1 deletion command/diagnostic.go
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
14 changes: 14 additions & 0 deletions command/ping.go
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
package command

import (
"strings"
)

func (cmd *Command) ping() {
msg, status := cmd.c.Ping(cmd.peerID)
if !status {
Expand All @@ -8,3 +12,13 @@ func (cmd *Command) ping() {
cmd.log.Info("Ping response received successfully", "message", msg)
}
}

func (cmd *Command) checkQuorumStatus() {
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 {
cmd.log.Error("Quorum is not setup in ", cmd.quorumAddr, " message ", msg)
}
}
2 changes: 2 additions & 0 deletions core/core.go
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ const (
APIGetTokenNumber string = "/api/get-token-number"
APIGetMigratedTokenStatus string = "/api/get-Migrated-token-status"
APISyncDIDArbitration string = "/api/sync-did-arbitration"
APICheckQuorumStatusPath string = "/api/check-quorum-status"
)

const (
Expand Down Expand Up @@ -318,6 +319,7 @@ func (c *Core) SetupCore() error {
}
c.w.SetupWallet(c.ipfs)
c.PingSetup()
c.CheckQuorumStatusSetup()
c.peerSetup()
c.w.AddDIDLastChar()
c.SetupToken()
Expand Down
58 changes: 58 additions & 0 deletions core/diagnostic.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
package core

import (
"fmt"
"strings"
"time"

"github.com/rubixchain/rubixgoplatform/block"
Expand Down Expand Up @@ -205,3 +207,59 @@ 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, 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 the Minimum Quorum Required
for i := 0; i < len(ql); i += MinQuorumRequired {
end := i + MinQuorumRequired
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 {
opError = nil
parts := strings.Split(item, ".")
if len(parts) != 2 {
continue
}
peerID := parts[0]
did := parts[1]
msg, _, err := c.CheckQuorumStatus(peerID, did)
if err != nil || strings.Contains(msg, "Quorum Connection Error") {
c.log.Error("Failed to check quorum status:", err)
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",
// set allQuorumSetup to false and break the loop
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",
// append the group to finalQl
if allQuorumSetup {
finalQl = append(finalQl, group...)
break
}
}
// Return finalQl
return finalQl, opError
}
47 changes: 47 additions & 0 deletions core/ping.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package core

import (
"fmt"
"net/http"
"time"

Expand All @@ -23,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")
Expand Down Expand Up @@ -51,3 +57,44 @@ 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"
resp.Status = false
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, bool, error) { //
q := make(map[string]string)
p, err := c.pm.OpenPeerConn(peerID, "", c.getCoreAppName(peerID))
if err != nil {
return "Quorum Connection Error", false, fmt.Errorf("quorum connection error")
}
// Close the p2p before exit
defer p.Close()
q["did"] = did
var checkQuorumStatusResponse PingResponse
err = p.SendJSONRequest("GET", APICheckQuorumStatusPath, q, nil, &checkQuorumStatusResponse, false, 2*time.Minute)
if err != nil {
return "Send Json Request error ", false, err
}
return checkQuorumStatusResponse.Message, checkQuorumStatusResponse.Status, nil
}
5 changes: 0 additions & 5 deletions core/quorum.go
Original file line number Diff line number Diff line change
@@ -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"
Expand Down Expand Up @@ -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
Expand All @@ -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)
Expand Down
23 changes: 19 additions & 4 deletions core/quorum_initiator.go
Original file line number Diff line number Diff line change
Expand Up @@ -277,19 +277,34 @@ 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 {
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
}

c.qlock.Lock()
c.quorumRequest[cr.ReqID] = &cs
c.pd[cr.ReqID] = &pd
c.qlock.Unlock()
cr.QuorumList = ql
defer func() {
c.qlock.Lock()
delete(c.quorumRequest, cr.ReqID)
delete(c.pd, cr.ReqID)
c.qlock.Unlock()
}()

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
Expand Down Expand Up @@ -799,7 +814,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 {
Expand Down
4 changes: 3 additions & 1 deletion core/quorum_validation.go
Original file line number Diff line number Diff line change
Expand Up @@ -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)
}
Expand Down Expand Up @@ -393,6 +394,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"
Expand Down
2 changes: 1 addition & 1 deletion core/smart_contract.go
Original file line number Diff line number Diff line change
Expand Up @@ -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{
Expand Down
4 changes: 2 additions & 2 deletions core/transfer.go
Original file line number Diff line number Diff line change
Expand Up @@ -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()
Expand Down
2 changes: 1 addition & 1 deletion core/wallet/token.go
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down
Loading

0 comments on commit b23a852

Please sign in to comment.