github.com/fozzysec/SiaPrime@v0.0.0-20190612043147-66c8e8d11fe3/modules/miningpool/stratum_test.go (about) 1 package pool 2 3 import ( 4 "bufio" 5 "encoding/json" 6 "fmt" 7 "net" 8 "testing" 9 "time" 10 11 "SiaPrime/build" 12 "SiaPrime/types" 13 "gitlab.com/NebulousLabs/errors" 14 ) 15 16 // TestStratumServer would test before and after a connections is made to the server 17 func TestStratumServer(t *testing.T) { 18 //t.Log("TestStratumServer") 19 if !build.POOL { 20 return 21 } 22 pt, err := newPoolTester(t.Name(), 0) 23 defer pt.Close() 24 if err != nil { 25 t.Fatal(err) 26 } 27 28 if len(pt.mpool.dispatcher.handlers) != 0 { 29 t.Fatal(errors.New(fmt.Sprintf("wrong handler number %d", len(pt.mpool.dispatcher.handlers)))) 30 } 31 32 time.Sleep(time.Millisecond * 2) 33 34 //t.Logf("listening on port: %v\n", pt.mpool.InternalSettings().PoolNetworkPort) 35 socket, err := net.Dial("tcp", fmt.Sprintf(":%d", pt.mpool.InternalSettings().PoolNetworkPort)) 36 if err != nil { 37 t.Fatal(err) 38 } 39 40 time.Sleep(time.Millisecond * 2) 41 42 if len(pt.mpool.dispatcher.handlers) != 1 { 43 t.Fatal(errors.New(fmt.Sprintf("wrong handler number %d", len(pt.mpool.dispatcher.handlers)))) 44 } 45 46 socket.Close() 47 48 time.Sleep(time.Millisecond * 2) 49 // after connection close, handler should be deleted 50 if len(pt.mpool.dispatcher.handlers) != 0 { 51 t.Fatal(errors.New(fmt.Sprintf("wrong handler number %d", len(pt.mpool.dispatcher.handlers)))) 52 } 53 } 54 55 func createAuthorizeRequest(t *testing.T, port int, waitchan chan int, tID uint64, autoclose bool) net.Conn { 56 //fmt.Printf("listening on port: %v\n", pt.mpool.InternalSettings().PoolNetworkPort) 57 socket, err := net.DialTimeout("tcp", fmt.Sprintf(":%d", port), 3*time.Second) 58 if err != nil { 59 t.Fatal(err) 60 } 61 defer func() { 62 if autoclose { 63 socket.Close() 64 } 65 //fmt.Println("Closed socket: ", tID) 66 }() 67 //fmt.Println("listening successfully") 68 69 args := []string{fmt.Sprintf("%s.%s", tAddress, tUser), ""} 70 params := make([]interface{}, len(args)) 71 for i, v := range args { 72 params[i] = v 73 } 74 req := types.StratumRequest{Method: "mining.authorize", Params: params, ID: tID} 75 rawmsg, err := json.Marshal(req) 76 if err != nil { 77 t.Fatal(err) 78 return nil 79 } 80 rawmsg = append(rawmsg, []byte("\n")...) 81 socket.SetWriteDeadline(time.Now().Add(1 * time.Second)) 82 if waitchan != nil { 83 waitchan <- 2 84 } 85 _, err = socket.Write(rawmsg) 86 if err != nil { 87 t.Fatal(err) 88 return nil 89 } else if waitchan != nil { 90 waitchan <- 0 91 } 92 for { 93 //fmt.Printf("Creating NewReader for socket\n") 94 reader := bufio.NewReader(socket) 95 96 //fmt.Printf("Reading from socket\n") 97 rawmessage, err := reader.ReadString('\n') 98 if err != nil { 99 t.Fatal(err) 100 } 101 102 r := types.StratumResponse{} 103 err = json.Unmarshal([]byte(rawmessage), &r) 104 if err != nil { 105 //fmt.Println(string(rawmessage)) 106 t.Fatal(err) 107 } 108 109 if r.ID == tID { 110 break 111 } else { 112 t.Fatal("got a wrong message: ", rawmessage) 113 } 114 } 115 if waitchan != nil { 116 waitchan <- 1 117 } 118 return socket 119 } 120 121 func TestStratumAuthorize(t *testing.T) { 122 if !build.POOL { 123 return 124 } 125 pt, err := newPoolTester(t.Name(), 0) 126 defer pt.Close() 127 if err != nil { 128 t.Fatal(err) 129 } 130 time.Sleep(time.Millisecond * 2) 131 port := pt.mpool.InternalSettings().PoolNetworkPort 132 createAuthorizeRequest(t, port, nil, 123, true) 133 } 134 135 func TestStratumAuthorizeHeavyLoad(t *testing.T) { 136 if !build.POOL { 137 return 138 } 139 pt, err := newPoolTester(t.Name(), 0) 140 defer pt.Close() 141 if err != nil { 142 t.Fatal(err) 143 } 144 time.Sleep(time.Millisecond * 2) 145 port := pt.mpool.InternalSettings().PoolNetworkPort 146 // we start getting socket issues when we get into 147 // 1000+ - not sure why, but I think the socket buffers 148 // may get filled up before we can read them 149 num := 100 150 numPrepWritten := 0 151 numWritten := 0 152 numAuthed := 0 153 waitchan := make(chan int, num*3) 154 for i := 1; i < num+1; i++ { 155 go createAuthorizeRequest(t, port, waitchan, uint64(i), true) 156 // If we don't sleep for a ms here, we get a deadlock. 157 // I'm not sure why. 158 time.Sleep(2 * time.Millisecond) 159 } 160 for { 161 select { 162 case info := <-waitchan: 163 if info == 0 { 164 numWritten += 1 165 } else if info == 1 { 166 numAuthed += 1 167 } else if info == 2 { 168 numPrepWritten += 1 169 } 170 //fmt.Printf("Prep Written: %d, Written: %d, Authed: %d, Remaining Connections: %d, Total Connections Opened: %d\n", numPrepWritten, numWritten, numAuthed, pt.mpool.NumConnections(), pt.mpool.NumConnectionsOpened()) 171 if numAuthed == num { 172 return 173 } 174 default: 175 } 176 time.Sleep(2 * time.Millisecond) 177 } 178 } 179 180 func createSubscribeRequest(t *testing.T, socket net.Conn, waitchan chan int, tID uint64, autoclose bool) net.Conn { 181 defer func() { 182 if autoclose { 183 socket.Close() 184 } 185 }() 186 187 args := []string{"testminer"} 188 params := make([]interface{}, len(args)) 189 for i, v := range args { 190 params[i] = v 191 } 192 req := types.StratumRequest{Method: "mining.subscribe", Params: params, ID: tID} 193 rawmsg, err := json.Marshal(req) 194 if err != nil { 195 return nil 196 } 197 198 rawmsg = append(rawmsg, []byte("\n")...) 199 _, err = socket.Write(rawmsg) 200 //fmt.Println("Subscribe write completed: ", tID) 201 if err != nil { 202 return nil 203 } 204 205 for { 206 reader := bufio.NewReader(socket) 207 208 rawmessage, err := reader.ReadString('\n') 209 // fmt.Println(rawmessage) 210 if err != nil { 211 t.Fatal(err) 212 } 213 214 r := types.StratumResponse{} 215 err = json.Unmarshal([]byte(rawmessage), &r) 216 if err != nil { 217 t.Fatal(err) 218 } 219 if r.ID == tID { 220 //fmt.Printf("MATCH %d: %s\n", r.ID, rawmessage) 221 if r.Error != nil { 222 rErr := r.Error 223 t.Fatal(errors.New(rErr[0].(string))) 224 } 225 resp := r.Result.([]interface{}) 226 if len(resp) != 3 { 227 t.Fatal(errors.New(fmt.Sprintf("wrong response number %d", len(resp)))) 228 } 229 230 break 231 } else { 232 //fmt.Printf("%d: %s\n", r.ID, rawmessage) 233 } 234 } 235 //fmt.Println("Subscribe completed: ", tID) 236 if waitchan != nil { 237 waitchan <- 1 238 } else { 239 //fmt.Println("NOT sending waitchan: ", tID) 240 } 241 //fmt.Println("waitchan sent: ", tID) 242 return socket 243 //fmt.Println("exited TestStratumSubscribe") 244 } 245 246 func TestStratumSubscribe(t *testing.T) { 247 //fmt.Println("TestStratumSubscribe") 248 if !build.POOL { 249 return 250 } 251 pt, err := newPoolTester(t.Name(), 0) 252 defer pt.Close() 253 if err != nil { 254 t.Fatal(err) 255 } 256 time.Sleep(time.Millisecond * 2) 257 port := pt.mpool.InternalSettings().PoolNetworkPort 258 socket := createAuthorizeRequest(t, port, nil, 123, false) 259 createSubscribeRequest(t, socket, nil, 123, true) 260 } 261 262 func TestStratumSubscribeHeavyLoad(t *testing.T) { 263 if !build.POOL { 264 return 265 } 266 pt, err := newPoolTester(t.Name(), 0) 267 defer pt.Close() 268 if err != nil { 269 t.Fatal(err) 270 } 271 time.Sleep(time.Millisecond * 2) 272 port := pt.mpool.InternalSettings().PoolNetworkPort 273 num := 10 274 //numPrepWritten := 0 275 //numWritten := 0 276 numSubscribed := 0 277 waitchan := make(chan int, num*3) 278 for i := 1; i < num+1; i++ { 279 socket := createAuthorizeRequest(t, port, nil, uint64(i), false) 280 go createSubscribeRequest(t, socket, waitchan, uint64(i), true) 281 // If we don't sleep for a ms here, we get a deadlock. 282 // I'm not sure why. 283 time.Sleep(2 * time.Millisecond) 284 } 285 for { 286 select { 287 case info := <-waitchan: 288 if info == 1 { 289 numSubscribed += 1 290 } 291 //fmt.Printf("Subscribed: %d, Remaining Connections: %d, Total Connections Opened: %d\n", numSubscribed, pt.mpool.NumConnections(), pt.mpool.NumConnectionsOpened()) 292 if numSubscribed == num { 293 return 294 } 295 default: 296 } 297 time.Sleep(2 * time.Millisecond) 298 } 299 }