2018-09-01 01:50:22 +02:00
|
|
|
package reflector
|
|
|
|
|
|
|
|
import (
|
|
|
|
"encoding/hex"
|
|
|
|
"encoding/json"
|
|
|
|
"net/http"
|
|
|
|
"strconv"
|
|
|
|
"strings"
|
2018-09-20 17:24:36 +02:00
|
|
|
"time"
|
2018-09-01 01:50:22 +02:00
|
|
|
|
2018-09-20 17:24:36 +02:00
|
|
|
"github.com/lbryio/reflector.go/store"
|
2018-09-01 01:50:22 +02:00
|
|
|
"github.com/lbryio/reflector.go/wallet"
|
|
|
|
|
2019-11-14 01:11:35 +01:00
|
|
|
"github.com/lbryio/lbry.go/v2/extras/errors"
|
2018-09-01 01:50:22 +02:00
|
|
|
|
2018-09-20 17:24:36 +02:00
|
|
|
log "github.com/sirupsen/logrus"
|
2018-09-01 01:50:22 +02:00
|
|
|
)
|
|
|
|
|
2019-07-31 00:02:32 +02:00
|
|
|
const blocklistURL = "https://api.lbry.com/file/list_blocked"
|
2018-09-01 01:50:22 +02:00
|
|
|
|
2018-09-20 17:24:36 +02:00
|
|
|
func (s *Server) enableBlocklist(b store.Blocklister) {
|
2019-01-16 17:41:58 +01:00
|
|
|
// TODO: updateBlocklist should be killed when server is shutting down
|
2018-09-20 17:24:36 +02:00
|
|
|
updateBlocklist(b)
|
|
|
|
t := time.NewTicker(12 * time.Hour)
|
|
|
|
for {
|
|
|
|
select {
|
|
|
|
case <-s.grp.Ch():
|
|
|
|
return
|
|
|
|
case <-t.C:
|
|
|
|
updateBlocklist(b)
|
|
|
|
}
|
|
|
|
}
|
2018-09-01 01:50:22 +02:00
|
|
|
}
|
|
|
|
|
2018-09-20 17:24:36 +02:00
|
|
|
func updateBlocklist(b store.Blocklister) {
|
|
|
|
values, err := blockedSdHashes()
|
|
|
|
if err != nil {
|
|
|
|
log.Error(err)
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
2019-12-28 19:32:41 +01:00
|
|
|
for name, v := range values {
|
2018-09-20 17:24:36 +02:00
|
|
|
if v.Err != nil {
|
2020-03-19 05:30:21 +01:00
|
|
|
log.Error(errors.FullTrace(errors.Err("blocklist: %s: %s", name, v.Err)))
|
2018-09-20 17:24:36 +02:00
|
|
|
continue
|
|
|
|
}
|
|
|
|
|
|
|
|
err = b.Block(v.Value)
|
|
|
|
if err != nil {
|
|
|
|
log.Error(err)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-09-20 20:24:30 +02:00
|
|
|
func blockedSdHashes() (map[string]valOrErr, error) {
|
2018-09-01 01:50:22 +02:00
|
|
|
resp, err := http.Get(blocklistURL)
|
|
|
|
if err != nil {
|
|
|
|
return nil, errors.Err(err)
|
|
|
|
}
|
2018-09-24 16:31:14 +02:00
|
|
|
defer func() {
|
|
|
|
err := resp.Body.Close()
|
|
|
|
if err != nil {
|
2020-02-26 16:02:53 +01:00
|
|
|
log.Errorln(errors.Err(err))
|
2018-09-24 16:31:14 +02:00
|
|
|
}
|
|
|
|
}()
|
2018-09-01 01:50:22 +02:00
|
|
|
|
2018-09-20 17:24:36 +02:00
|
|
|
var r struct {
|
|
|
|
Success bool `json:"success"`
|
|
|
|
Error string `json:"error"`
|
|
|
|
Data struct {
|
|
|
|
Outpoints []string `json:"outpoints"`
|
|
|
|
} `json:"data"`
|
|
|
|
}
|
|
|
|
|
2018-09-01 01:50:22 +02:00
|
|
|
if err = json.NewDecoder(resp.Body).Decode(&r); err != nil {
|
|
|
|
return nil, errors.Err(err)
|
|
|
|
}
|
|
|
|
|
|
|
|
if !r.Success {
|
|
|
|
return nil, errors.Prefix("list_blocked API call", r.Error)
|
|
|
|
}
|
|
|
|
|
2018-09-11 13:41:29 +02:00
|
|
|
return sdHashesForOutpoints(r.Data.Outpoints)
|
|
|
|
}
|
2018-09-01 01:50:22 +02:00
|
|
|
|
2018-09-20 20:24:30 +02:00
|
|
|
type valOrErr struct {
|
2018-09-11 13:41:29 +02:00
|
|
|
Value string
|
|
|
|
Err error
|
2018-09-01 01:50:22 +02:00
|
|
|
}
|
|
|
|
|
2018-09-11 13:41:29 +02:00
|
|
|
// sdHashesForOutpoints queries wallet server for the sd hashes in a given outpoints
|
2018-09-20 20:24:30 +02:00
|
|
|
func sdHashesForOutpoints(outpoints []string) (map[string]valOrErr, error) {
|
|
|
|
values := make(map[string]valOrErr)
|
2018-09-01 01:50:22 +02:00
|
|
|
|
|
|
|
node := wallet.NewNode()
|
2019-01-16 17:41:58 +01:00
|
|
|
defer node.Shutdown()
|
2018-09-20 17:24:36 +02:00
|
|
|
err := node.Connect([]string{
|
2020-02-06 17:08:32 +01:00
|
|
|
"spv4.lbry.com:50001",
|
2019-07-30 23:06:35 +02:00
|
|
|
"spv5.lbry.com:50001",
|
2019-12-28 19:32:41 +01:00
|
|
|
"spv7.lbry.com:50001",
|
|
|
|
"spv9.lbry.com:50001",
|
2020-02-06 17:08:32 +01:00
|
|
|
"spv15.lbry.com:50001",
|
|
|
|
"spv17.lbry.com:50001",
|
|
|
|
"spv25.lbry.com:50001",
|
2018-09-20 17:24:36 +02:00
|
|
|
}, nil)
|
2018-09-01 01:50:22 +02:00
|
|
|
if err != nil {
|
2020-02-26 16:02:53 +01:00
|
|
|
return nil, errors.Err(err)
|
2018-09-01 01:50:22 +02:00
|
|
|
}
|
|
|
|
|
2018-09-11 13:41:29 +02:00
|
|
|
for _, outpoint := range outpoints {
|
|
|
|
parts := strings.Split(outpoint, ":")
|
|
|
|
if len(parts) != 2 {
|
2018-09-20 20:24:30 +02:00
|
|
|
values[outpoint] = valOrErr{Err: errors.Err("invalid outpoint format")}
|
2018-09-11 13:41:29 +02:00
|
|
|
continue
|
|
|
|
}
|
|
|
|
|
|
|
|
nout, err := strconv.Atoi(parts[1])
|
|
|
|
if err != nil {
|
2018-09-20 20:24:30 +02:00
|
|
|
values[outpoint] = valOrErr{Err: errors.Prefix("invalid nout", err)}
|
2018-09-11 13:41:29 +02:00
|
|
|
continue
|
|
|
|
}
|
|
|
|
|
2019-12-28 19:32:41 +01:00
|
|
|
claim, err := node.GetClaimInTx(parts[0], nout)
|
2018-09-11 13:41:29 +02:00
|
|
|
if err != nil {
|
2018-09-20 20:24:30 +02:00
|
|
|
values[outpoint] = valOrErr{Err: err}
|
2018-09-11 13:41:29 +02:00
|
|
|
continue
|
|
|
|
}
|
|
|
|
|
2019-12-28 19:32:41 +01:00
|
|
|
hash := hex.EncodeToString(claim.GetStream().GetSource().GetSdHash())
|
|
|
|
values[outpoint] = valOrErr{Value: hash, Err: nil}
|
2018-09-01 01:50:22 +02:00
|
|
|
}
|
|
|
|
|
2018-09-11 13:41:29 +02:00
|
|
|
return values, nil
|
2018-09-01 01:50:22 +02:00
|
|
|
}
|