github.com/SimplyVC/oasis_api_server/src@v0.0.0-20220105202803-ad2c5a67840e/handlers/scheduler_handler.go (about) 1 package handlers 2 3 import ( 4 "context" 5 "encoding/json" 6 "net/http" 7 8 "google.golang.org/grpc" 9 10 lgr "github.com/SimplyVC/oasis_api_server/src/logger" 11 "github.com/SimplyVC/oasis_api_server/src/responses" 12 "github.com/SimplyVC/oasis_api_server/src/rpc" 13 common_namespace "github.com/oasisprotocol/oasis-core/go/common" 14 scheduler "github.com/oasisprotocol/oasis-core/go/scheduler/api" 15 ) 16 17 // loadSchedulerClient loads scheduler client and returns it 18 func loadSchedulerClient(socket string) (*grpc.ClientConn, scheduler.Backend) { 19 20 // Attempt to load connection with scheduler client 21 connection, schedulerClient, err := rpc.SchedulerClient(socket) 22 if err != nil { 23 lgr.Error.Println( 24 "Failed to establish connection to scheduler client : ", 25 err) 26 return nil, nil 27 } 28 return connection, schedulerClient 29 } 30 31 // GetValidators returns vector of consensus validators for given epoch. 32 func GetValidators(w http.ResponseWriter, r *http.Request) { 33 34 // Add header so that received knows they're receiving JSON 35 w.Header().Add("Content-Type", "application/json") 36 37 // Retrieving name of node from query request 38 nodeName := r.URL.Query().Get("name") 39 confirmation, socket := checkNodeName(nodeName) 40 if !confirmation { 41 42 // Stop code here no need to establish connection and reply 43 json.NewEncoder(w).Encode(responses.ErrorResponse{ 44 Error: "Node name requested doesn't exist"}) 45 return 46 } 47 48 // Retrieving height of node from query request 49 recvHeight := r.URL.Query().Get("height") 50 height := checkHeight(recvHeight) 51 if height == -1 { 52 53 // Stop code here no need to establish connection and reply 54 json.NewEncoder(w).Encode(responses.ErrorResponse{ 55 Error: "Unexpected value found, height needs to be " + 56 "a string representing an int!"}) 57 return 58 } 59 60 // Attempt to load connection with scheduler client 61 connection, sc := loadSchedulerClient(socket) 62 63 // Close connection once code underneath executes 64 defer connection.Close() 65 66 // If null object was retrieved send response 67 if sc == nil { 68 69 // Stop code here faild to establish connection and reply 70 json.NewEncoder(w).Encode(responses.ErrorResponse{ 71 Error: "Failed to establish connection using socket: " + 72 socket}) 73 return 74 } 75 76 // Retrieve validators at given block height 77 validators, err := sc.GetValidators(context.Background(), height) 78 if err != nil { 79 json.NewEncoder(w).Encode(responses.ErrorResponse{ 80 Error: "Failed to get Validators!"}) 81 lgr.Error.Println("Request at /api/scheduler/validators "+ 82 "failed to retrieve validators : ", err) 83 return 84 } 85 86 // Responding with Validators retrieved from scheduler client 87 lgr.Info.Println("Request at /api/scheduler/validators responding " + 88 "with Validators!") 89 json.NewEncoder(w).Encode(responses.ValidatorsResponse{ 90 Validators: validators}) 91 } 92 93 // GetCommittees returns vector of committees for given 94 // runtime ID, at specified block height, and optional callback 95 // for querying beacon for given epoch/block height. 96 func GetCommittees(w http.ResponseWriter, r *http.Request) { 97 98 // Add header so that received knows they're receiving JSON 99 w.Header().Add("Content-Type", "application/json") 100 101 // Retrieving name of node from query request 102 nodeName := r.URL.Query().Get("name") 103 confirmation, socket := checkNodeName(nodeName) 104 if !confirmation { 105 // Stop code here no need to establish connection and reply 106 json.NewEncoder(w).Encode(responses.ErrorResponse{ 107 Error: "Node name requested doesn't exist"}) 108 return 109 } 110 111 // Retrieving height from query request 112 recvHeight := r.URL.Query().Get("height") 113 height := checkHeight(recvHeight) 114 if height == -1 { 115 // Stop code here no need to establish connection and reply 116 json.NewEncoder(w).Encode(responses.ErrorResponse{ 117 Error: "Unexpected value found, height needs to be " + 118 "a string representing an int!"}) 119 return 120 } 121 122 // Note Make sure that private key that is being sent is coded properly 123 // Example A1X90rT/WK4AOTh/dJsUlOqNDV/nXM6ZU+h+blS9pto= should be 124 // A1X90rT/WK4AOTh/dJsUlOqNDV/nXM6ZU%2Bh%2BblS9pto= 125 var nameSpace common_namespace.Namespace 126 nmspace := r.URL.Query().Get("namespace") 127 if len(nmspace) == 0 { 128 129 // Stop code here no need to establish connection and reply 130 lgr.Warning.Println("Request at /api/scheduler/committees failed" + 131 ", namespace can't be empty!") 132 json.NewEncoder(w).Encode(responses.ErrorResponse{ 133 Error: "namespace can't be empty!"}) 134 return 135 } 136 137 // Unmarshal text into namespace object to be used in query 138 err := nameSpace.UnmarshalText([]byte(nmspace)) 139 if err != nil { 140 lgr.Error.Println("Failed to UnmarshalText into Namespace", err) 141 json.NewEncoder(w).Encode(responses.ErrorResponse{ 142 Error: "Failed to UnmarshalText into Namespace."}) 143 return 144 } 145 146 // Attempt to load connection with scheduler client 147 connection, sc := loadSchedulerClient(socket) 148 149 // Close connection once code underneath executes 150 defer connection.Close() 151 152 // If null object was retrieved send response 153 if sc == nil { 154 155 // Stop code here faild to establish connection and reply 156 json.NewEncoder(w).Encode(responses.ErrorResponse{ 157 Error: "Failed to establish connection using socket: " + 158 socket}) 159 return 160 } 161 162 // Create query to be used to retrieve Committees 163 query := scheduler.GetCommitteesRequest{Height: height, 164 RuntimeID: nameSpace} 165 166 // Retrieving Committees using query above 167 committees, err := sc.GetCommittees(context.Background(), &query) 168 if err != nil { 169 json.NewEncoder(w).Encode(responses.ErrorResponse{ 170 Error: "Failed to get Committees!"}) 171 lgr.Error.Println("Request at /api/scheduler/committees "+ 172 "failed to retrieve committees : ", err) 173 return 174 } 175 176 // Responding with committees that were retrieved from scheduler client 177 lgr.Info.Println("Request at /api/scheduler/committees responding " + 178 "with Committees!") 179 json.NewEncoder(w).Encode(responses.CommitteesResponse{ 180 Committee: committees}) 181 } 182 183 // GetSchedulerStateToGenesis returns genesis state of scheduler at the 184 // specified block height. 185 func GetSchedulerStateToGenesis(w http.ResponseWriter, r *http.Request) { 186 187 // Add header so that received knows they're receiving JSON 188 w.Header().Add("Content-Type", "application/json") 189 190 // Retrieving name of node from query request 191 nodeName := r.URL.Query().Get("name") 192 confirmation, socket := checkNodeName(nodeName) 193 if !confirmation { 194 195 // Stop code here no need to establish connection and reply 196 json.NewEncoder(w).Encode(responses.ErrorResponse{ 197 Error: "Node name requested doesn't exist"}) 198 return 199 } 200 201 // Retrieving height from query request 202 recvHeight := r.URL.Query().Get("height") 203 height := checkHeight(recvHeight) 204 if height == -1 { 205 206 // Stop code here no need to establish connection and reply 207 json.NewEncoder(w).Encode(responses.ErrorResponse{ 208 Error: "Unexpected value found, height needs to be " + 209 "a string representing an int!"}) 210 return 211 } 212 213 // Attempt to load connection with scheduler client 214 connection, sc := loadSchedulerClient(socket) 215 216 // Close connection once code underneath executes 217 defer connection.Close() 218 219 // If null object was retrieved send response 220 if sc == nil { 221 222 // Stop code here faild to establish connection and reply 223 json.NewEncoder(w).Encode(responses.ErrorResponse{ 224 Error: "Failed to establish connection using socket: " + 225 socket}) 226 return 227 } 228 229 // Retrieve genesis state of scheduler at specific block height 230 gensis, err := sc.StateToGenesis(context.Background(), height) 231 if err != nil { 232 json.NewEncoder(w).Encode(responses.ErrorResponse{ 233 Error: "Failed to get Scheduler Genesis State!"}) 234 lgr.Error.Println("Request at /api/scheduler/genesis failed "+ 235 "to retrieve Scheduler Genesis State : ", err) 236 return 237 } 238 239 // Responding with genesis state retrieved above 240 lgr.Info.Println("Request at /api/scheduler/genesis responding with " + 241 "scheduler genesis state!") 242 json.NewEncoder(w).Encode(responses.SchedulerGenesisState{ 243 SchedulerGenesisState: gensis}) 244 }