Use event based system for reporting
This commit is contained in:
parent
ffd83d4a2c
commit
840d0c8f3a
375
bot.go
375
bot.go
|
@ -1,10 +1,15 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"flag"
|
||||
"fmt"
|
||||
utils2 "git.gammaspectra.live/P2Pool/p2pool-observer/cmd/utils"
|
||||
"git.gammaspectra.live/P2Pool/p2pool-observer/index"
|
||||
"git.gammaspectra.live/P2Pool/p2pool-observer/monero/randomx"
|
||||
"git.gammaspectra.live/P2Pool/p2pool-observer/p2pool/sidechain"
|
||||
"git.gammaspectra.live/P2Pool/p2pool-observer/types"
|
||||
"git.gammaspectra.live/P2Pool/p2pool-observer/utils"
|
||||
hbot "github.com/whyrusleeping/hellabot"
|
||||
|
@ -15,7 +20,10 @@ import (
|
|||
"log"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"nhooyr.io/websocket"
|
||||
"nhooyr.io/websocket/wsjson"
|
||||
"os"
|
||||
"regexp"
|
||||
"strings"
|
||||
"sync"
|
||||
"time"
|
||||
|
@ -56,6 +64,15 @@ const FormatItalic = "\x1D"
|
|||
const FormatUnderline = "\x1F"
|
||||
const FormatReset = "\x0F"
|
||||
|
||||
var guestUserRegex = regexp.MustCompile("^Guest[0-9]+_*$")
|
||||
|
||||
func isNickAllowed(nick string) error {
|
||||
if guestUserRegex.MatchString(nick) {
|
||||
return errors.New("guest user is not allowed")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func main() {
|
||||
ircHost := flag.String("irc-host", "irc.libera.chat", "")
|
||||
ircPort := flag.Uint("irc-port", 6697, "")
|
||||
|
@ -72,20 +89,61 @@ func main() {
|
|||
flag.Parse()
|
||||
|
||||
type channelEntry struct {
|
||||
ApiEndpoint string
|
||||
Channel string
|
||||
Name string
|
||||
ApiEndpoint string
|
||||
Channel string
|
||||
Name string
|
||||
PreviousBlocks foundBlocks
|
||||
LastWindowMainDifficulty struct {
|
||||
Height uint64
|
||||
Difficulty uint64
|
||||
}
|
||||
PoolInfo map[string]any
|
||||
Consensus *sidechain.Consensus
|
||||
Window map[types.Hash]*index.SideBlock
|
||||
|
||||
LastBlocks foundBlocks
|
||||
Ws *websocket.Conn
|
||||
}
|
||||
|
||||
const lastBlocksCount = 10
|
||||
const numberOfBlockHistoryToKeep = 10
|
||||
|
||||
getLastBlocks := func(host string) (result foundBlocks) {
|
||||
getPoolInfo := func(host string) map[string]any {
|
||||
var basePoolInfo map[string]any
|
||||
|
||||
for {
|
||||
func() {
|
||||
uri, _ := url.Parse(host + "/api/pool_info")
|
||||
if response, err := http.DefaultClient.Do(&http.Request{
|
||||
Method: "GET",
|
||||
URL: uri,
|
||||
}); err != nil {
|
||||
return
|
||||
} else {
|
||||
defer response.Body.Close()
|
||||
if response.StatusCode == http.StatusOK {
|
||||
if strings.Index(response.Header.Get("content-type"), "/json") != -1 {
|
||||
decoder := json.NewDecoder(response.Body)
|
||||
decoder.UseNumber()
|
||||
err = decoder.Decode(&basePoolInfo)
|
||||
return
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
}()
|
||||
if basePoolInfo == nil || len(basePoolInfo) == 0 {
|
||||
time.Sleep(5)
|
||||
continue
|
||||
}
|
||||
break
|
||||
}
|
||||
return basePoolInfo
|
||||
}
|
||||
|
||||
getPreviousBlocks := func(host string) (result foundBlocks) {
|
||||
if host == "" {
|
||||
return nil
|
||||
}
|
||||
response, err := http.DefaultClient.Get(fmt.Sprintf("%s/api/found_blocks?limit=%d", host, lastBlocksCount))
|
||||
response, err := http.DefaultClient.Get(fmt.Sprintf("%s/api/found_blocks?limit=%d", host, numberOfBlockHistoryToKeep))
|
||||
if err != nil {
|
||||
return nil
|
||||
}
|
||||
|
@ -96,29 +154,35 @@ func main() {
|
|||
if err = json.Unmarshal(buf, &result); err != nil {
|
||||
return nil
|
||||
} else {
|
||||
//sort from oldest to newest
|
||||
slices.SortFunc(result, func(a, b *index.FoundBlock) bool {
|
||||
return a.MainBlock.Height < b.MainBlock.Height
|
||||
})
|
||||
return result
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
getBlockByMainId := func(host string, id types.Hash) *index.SideBlock {
|
||||
openWebsocket := func(host string) *websocket.Conn {
|
||||
if host == "" {
|
||||
return nil
|
||||
}
|
||||
response, err := http.DefaultClient.Get(fmt.Sprintf("%s/api/block_by_id/%s", host, id.String()))
|
||||
if err != nil {
|
||||
return nil
|
||||
}
|
||||
defer response.Body.Close()
|
||||
if buf, err := io.ReadAll(response.Body); err != nil {
|
||||
return nil
|
||||
} else {
|
||||
var result index.SideBlock
|
||||
if err = json.Unmarshal(buf, &result); err != nil {
|
||||
ctx, cancel := context.WithTimeout(context.Background(), time.Second*30)
|
||||
defer cancel()
|
||||
|
||||
u, _ := url.Parse(host)
|
||||
if u.Scheme == "https" {
|
||||
c, _, err := websocket.Dial(ctx, fmt.Sprintf("wss://%s/api/events", u.Host), nil)
|
||||
if err != nil {
|
||||
return nil
|
||||
} else {
|
||||
return &result
|
||||
}
|
||||
return c
|
||||
} else {
|
||||
c, _, err := websocket.Dial(ctx, fmt.Sprintf("ws://%s/api/events", u.Host), nil)
|
||||
if err != nil {
|
||||
return nil
|
||||
}
|
||||
return c
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -152,6 +216,18 @@ func main() {
|
|||
|
||||
var channelEntries []*channelEntry
|
||||
|
||||
getWindowMainDifficulty := func(e *channelEntry, tipHeight uint64) uint64 {
|
||||
h := randomx.SeedHeight(tipHeight)
|
||||
if e.LastWindowMainDifficulty.Height == h {
|
||||
return e.LastWindowMainDifficulty.Difficulty
|
||||
}
|
||||
|
||||
//TODO
|
||||
return 0
|
||||
}
|
||||
|
||||
_ = getWindowMainDifficulty
|
||||
|
||||
for _, e := range strings.Split(*botChannels, ";") {
|
||||
e = strings.TrimSpace(e)
|
||||
if e == "" {
|
||||
|
@ -163,15 +239,31 @@ func main() {
|
|||
continue
|
||||
}
|
||||
|
||||
basePoolInfo := getPoolInfo(split[2])
|
||||
|
||||
consensusData, _ := json.Marshal(basePoolInfo["sidechain"].(map[string]any)["consensus"].(map[string]any))
|
||||
consensus, err := sidechain.NewConsensusFromJSON(consensusData)
|
||||
if err != nil {
|
||||
log.Panic(err)
|
||||
}
|
||||
|
||||
channelEntries = append(channelEntries, &channelEntry{
|
||||
ApiEndpoint: split[2],
|
||||
Channel: split[0],
|
||||
Name: split[1],
|
||||
LastBlocks: getLastBlocks(split[2]),
|
||||
ApiEndpoint: split[2],
|
||||
Channel: split[0],
|
||||
Name: split[1],
|
||||
Consensus: consensus,
|
||||
PreviousBlocks: getPreviousBlocks(split[2]),
|
||||
Ws: openWebsocket(split[2]),
|
||||
Window: make(map[types.Hash]*index.SideBlock),
|
||||
})
|
||||
|
||||
}
|
||||
|
||||
var onlineUsersLock sync.RWMutex
|
||||
var onlineUsers []string
|
||||
|
||||
var beforeJoiningChannels sync.Once
|
||||
|
||||
if bot, err := hbot.NewBot(fmt.Sprintf("%s:%d", *ircHost, *ircPort), *botNickName, func(bot *hbot.Bot) {
|
||||
bot.Nick = *botNickName
|
||||
bot.Realname = *botUserName
|
||||
|
@ -189,75 +281,19 @@ func main() {
|
|||
//unique channels
|
||||
slices.Sort(bot.Channels)
|
||||
bot.Channels = slices.Compact(bot.Channels)
|
||||
}); err != nil {
|
||||
log.Panic(err)
|
||||
} else {
|
||||
logHandler := log2.LvlFilterHandler(log2.LvlDebug, log2.StdoutHandler)
|
||||
bot.Logger.SetHandler(logHandler)
|
||||
|
||||
// see about irc.ERR_NICKNAMEINUSE or irc.ERR_NICKCOLLISION to recover nick
|
||||
// Trigger commands before joining channels
|
||||
bot.AddTrigger(hbot.Trigger{
|
||||
Condition: func(bot *hbot.Bot, m *hbot.Message) bool {
|
||||
return m.Command == irc.RPL_WELCOME || m.Command == irc.RPL_ENDOFMOTD // 001 or 372
|
||||
},
|
||||
Action: func(bot *hbot.Bot, m *hbot.Message) bool {
|
||||
beforeJoiningChannels.Do(func() {
|
||||
|
||||
var onlineUsersLock sync.RWMutex
|
||||
var onlineUsers []string
|
||||
|
||||
blockFound := func(e *channelEntry, b *index.FoundBlock, previous *index.FoundBlock) {
|
||||
uHeight := (b.SideHeight << 16) | (uint64(b.MainBlock.Id[0]) << 8) | uint64(b.MainBlock.Id[1])
|
||||
effort := float64(0)
|
||||
if previous != nil {
|
||||
effort = float64(b.CumulativeDifficulty.SubWrap(previous.CumulativeDifficulty).Mul64(100).Lo) / float64(b.MainBlock.Difficulty)
|
||||
}
|
||||
effortColor := FormatColorRed
|
||||
if effort < 200 {
|
||||
effortColor = FormatColorYellow
|
||||
}
|
||||
if effort < 100 {
|
||||
effortColor = FormatColorGreen
|
||||
}
|
||||
bot.Msg(e.Channel, fmt.Sprintf(
|
||||
"%sBLOCK FOUND%s on %s: Main height %s%d%s, Side height %d :: %s/s/%s :: Effort %s%.02f%%%s :: %s%d miners paid%s, total %s%s%s XMR%s :: Id %s%s",
|
||||
FormatColorLightGreen+FormatBold, FormatReset, e.Name,
|
||||
FormatColorRed, b.MainBlock.Height, FormatReset,
|
||||
b.SideHeight,
|
||||
e.ApiEndpoint, utils.EncodeBinaryNumber(uHeight),
|
||||
effortColor, effort, FormatReset,
|
||||
FormatColorOrange, b.WindowOutputs, FormatReset,
|
||||
FormatColorOrange, FormatBold, utils.XMRUnits(b.MainBlock.Reward), FormatReset,
|
||||
FormatItalic, utils.Shorten(b.MainBlock.Id.String(), 8),
|
||||
))
|
||||
|
||||
doPleromaPost(e, fmt.Sprintf(
|
||||
"BLOCK FOUND on %s, Main height %d, Side height %d :: %s/s/%s :: Effort %.02f%% :: %d miners paid, total %s XMR :: Id %s",
|
||||
e.Name,
|
||||
b.MainBlock.Height,
|
||||
b.SideHeight,
|
||||
e.ApiEndpoint,
|
||||
utils.EncodeBinaryNumber(uHeight),
|
||||
effort,
|
||||
b.WindowOutputs,
|
||||
utils.XMRUnits(b.MainBlock.Reward),
|
||||
b.MainBlock.Id,
|
||||
))
|
||||
}
|
||||
|
||||
blockOrphaned := func(e *channelEntry, b *index.FoundBlock) {
|
||||
bot.Msg(e.Channel, fmt.Sprintf(
|
||||
"%sBLOCK ORPHANED%s on %s: Main height %s%d%s, Side height %d :: Side Template Id %s%s%s :: Id %s%s",
|
||||
FormatColorLightGreen+FormatBold, FormatReset, e.Name,
|
||||
FormatColorRed, b.MainBlock.Height, FormatReset,
|
||||
b.SideHeight,
|
||||
FormatItalic, b.MainBlock.SideTemplateId, FormatReset,
|
||||
FormatItalic, b.MainBlock.Id,
|
||||
))
|
||||
|
||||
doPleromaPost(e, fmt.Sprintf(
|
||||
"BLOCK ORPHANED on %s, Main height %d, Side height %d :: Side Template Id %s :: Id %s",
|
||||
e.Name,
|
||||
b.MainBlock.Height,
|
||||
b.SideHeight,
|
||||
b.MainBlock.SideTemplateId,
|
||||
b.MainBlock.Id,
|
||||
))
|
||||
}
|
||||
})
|
||||
return false
|
||||
},
|
||||
})
|
||||
|
||||
// Track channel joins to have users nicks as connected
|
||||
bot.AddTrigger(hbot.Trigger{
|
||||
|
@ -351,6 +387,103 @@ func main() {
|
|||
return false
|
||||
},
|
||||
})
|
||||
}); err != nil {
|
||||
log.Panic(err)
|
||||
} else {
|
||||
logHandler := log2.LvlFilterHandler(log2.LvlDebug, log2.StdoutHandler)
|
||||
bot.Logger.SetHandler(logHandler)
|
||||
|
||||
// see about irc.ERR_NICKNAMEINUSE or irc.ERR_NICKCOLLISION to recover nick
|
||||
|
||||
shareFound := func(e *channelEntry, b *index.SideBlock, target string) {
|
||||
uHeight := (b.SideHeight << 16) | (uint64(b.MainId[0]) << 8) | uint64(b.MainId[1])
|
||||
|
||||
if b.UncleOf != types.ZeroHash {
|
||||
bot.Msg(target, fmt.Sprintf(
|
||||
"%sUNCLE SHARE FOUND%s on %s: Side height %s%d%s, Parent Side height %s%d%s :: %s/s/%s :: Accounted for %d%% of value :: Template Id %s%s%s :: Miner Address %s%s",
|
||||
FormatColorLightGreen+FormatBold, FormatReset, e.Name,
|
||||
FormatColorRed, b.SideHeight, FormatReset,
|
||||
FormatColorRed, b.EffectiveHeight, FormatReset,
|
||||
e.ApiEndpoint, utils.EncodeBinaryNumber(uHeight),
|
||||
100-e.Consensus.UnclePenalty,
|
||||
FormatItalic, utils.Shorten(b.TemplateId.String(), 8), FormatReset,
|
||||
FormatItalic, utils.Shorten(b.MinerAddress.ToBase58(), 10),
|
||||
))
|
||||
} else {
|
||||
uncleText := ""
|
||||
if len(b.Uncles) > 0 {
|
||||
uncleText = fmt.Sprintf(":: Includes %d uncle(s) for extra %d%% of their value ", len(b.Uncles), e.Consensus.UnclePenalty)
|
||||
}
|
||||
bot.Msg(target, fmt.Sprintf(
|
||||
"%sSHARE FOUND%s on %s: Side height %s%d%s :: %s/s/%s %s:: Template Id %s%s%s :: Miner Address %s%s",
|
||||
FormatColorLightGreen+FormatBold, FormatReset, e.Name,
|
||||
FormatColorRed, b.SideHeight, FormatReset,
|
||||
e.ApiEndpoint, utils.EncodeBinaryNumber(uHeight),
|
||||
uncleText,
|
||||
FormatItalic, utils.Shorten(b.TemplateId.String(), 8), FormatReset,
|
||||
FormatItalic, utils.Shorten(b.MinerAddress.ToBase58(), 10),
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
blockFound := func(e *channelEntry, b *index.FoundBlock, previous *index.FoundBlock) {
|
||||
uHeight := (b.SideHeight << 16) | (uint64(b.MainBlock.Id[0]) << 8) | uint64(b.MainBlock.Id[1])
|
||||
effort := float64(0)
|
||||
if previous != nil {
|
||||
effort = float64(b.CumulativeDifficulty.SubWrap(previous.CumulativeDifficulty).Mul64(100).Lo) / float64(b.MainBlock.Difficulty)
|
||||
}
|
||||
effortColor := FormatColorRed
|
||||
if effort < 200 {
|
||||
effortColor = FormatColorYellow
|
||||
}
|
||||
if effort < 100 {
|
||||
effortColor = FormatColorGreen
|
||||
}
|
||||
bot.Msg(e.Channel, fmt.Sprintf(
|
||||
"%sBLOCK FOUND%s on %s: Main height %s%d%s, Side height %d :: %s/s/%s :: Effort %s%.02f%%%s :: %s%d miners paid%s, total %s%s%s XMR%s :: Id %s%s",
|
||||
FormatColorLightGreen+FormatBold, FormatReset, e.Name,
|
||||
FormatColorRed, b.MainBlock.Height, FormatReset,
|
||||
b.SideHeight,
|
||||
e.ApiEndpoint, utils.EncodeBinaryNumber(uHeight),
|
||||
effortColor, effort, FormatReset,
|
||||
FormatColorOrange, b.WindowOutputs, FormatReset,
|
||||
FormatColorOrange, FormatBold, utils.XMRUnits(b.MainBlock.Reward), FormatReset,
|
||||
FormatItalic, utils.Shorten(b.MainBlock.Id.String(), 8),
|
||||
))
|
||||
|
||||
doPleromaPost(e, fmt.Sprintf(
|
||||
"BLOCK FOUND on %s, Main height %d, Side height %d :: %s/s/%s :: Effort %.02f%% :: %d miners paid, total %s XMR :: Id %s",
|
||||
e.Name,
|
||||
b.MainBlock.Height,
|
||||
b.SideHeight,
|
||||
e.ApiEndpoint,
|
||||
utils.EncodeBinaryNumber(uHeight),
|
||||
effort,
|
||||
b.WindowOutputs,
|
||||
utils.XMRUnits(b.MainBlock.Reward),
|
||||
b.MainBlock.Id,
|
||||
))
|
||||
}
|
||||
|
||||
blockOrphaned := func(e *channelEntry, b *index.SideBlock) {
|
||||
bot.Msg(e.Channel, fmt.Sprintf(
|
||||
"%sBLOCK ORPHANED%s on %s: Main height %s%d%s, Side height %d :: Side Template Id %s%s%s :: Id %s%s",
|
||||
FormatColorLightGreen+FormatBold, FormatReset, e.Name,
|
||||
FormatColorRed, b.MainHeight, FormatReset,
|
||||
b.SideHeight,
|
||||
FormatItalic, b.TemplateId, FormatReset,
|
||||
FormatItalic, b.MainId,
|
||||
))
|
||||
|
||||
doPleromaPost(e, fmt.Sprintf(
|
||||
"BLOCK ORPHANED on %s, Main height %d, Side height %d :: Side Template Id %s :: Id %s",
|
||||
e.Name,
|
||||
b.MainHeight,
|
||||
b.SideHeight,
|
||||
b.TemplateId,
|
||||
b.MainId,
|
||||
))
|
||||
}
|
||||
|
||||
//Private message
|
||||
bot.AddTrigger(hbot.Trigger{
|
||||
|
@ -367,45 +500,49 @@ func main() {
|
|||
},
|
||||
})
|
||||
|
||||
_ = shareFound
|
||||
|
||||
for _, e := range channelEntries {
|
||||
if e.ApiEndpoint == "" {
|
||||
continue
|
||||
}
|
||||
go func(e *channelEntry) {
|
||||
|
||||
for range time.NewTicker(time.Second * 5).C {
|
||||
lastBlocks := getLastBlocks(e.ApiEndpoint)
|
||||
slices.SortFunc(lastBlocks, func(a, b *index.FoundBlock) bool {
|
||||
return a.MainBlock.Height < b.MainBlock.Height
|
||||
})
|
||||
if len(lastBlocks) == 0 {
|
||||
continue
|
||||
if e.Ws == nil {
|
||||
log.Printf("[WS] WebSocket for %s is disconnected, retrying", e.ApiEndpoint)
|
||||
for ; e.Ws == nil; e.Ws = openWebsocket(e.ApiEndpoint) {
|
||||
time.Sleep(time.Second * 30)
|
||||
log.Printf("[WS] WebSocket for %s is disconnected, retrying again", e.ApiEndpoint)
|
||||
}
|
||||
for _, b := range lastBlocks {
|
||||
if e.LastBlocks.Get(b.MainBlock.Id) == nil {
|
||||
//new block
|
||||
e.LastBlocks = append(e.LastBlocks, b)
|
||||
}
|
||||
|
||||
blockFound(e, b, e.LastBlocks.GetPrevious(b))
|
||||
}
|
||||
}
|
||||
|
||||
for _, b := range e.LastBlocks {
|
||||
// no block on new returned blocks, check it did not get orphaned
|
||||
if lastBlocks.Get(b.MainBlock.Id) == nil {
|
||||
if sideBlock := getBlockByMainId(e.ApiEndpoint, b.MainBlock.Id); sideBlock != nil {
|
||||
if !sideBlock.MinedMainAtHeight {
|
||||
//got orphaned
|
||||
|
||||
blockOrphaned(e, b)
|
||||
}
|
||||
for {
|
||||
var event utils2.JSONEvent
|
||||
if err := wsjson.Read(context.Background(), e.Ws, &event); err != nil {
|
||||
e.Ws.Close(websocket.StatusGoingAway, "error on read "+err.Error())
|
||||
e.Ws = nil
|
||||
break
|
||||
} else {
|
||||
switch event.Type {
|
||||
case utils2.JSONEventSideBlock:
|
||||
//shareFound(e, event.SideBlock, "DataHoarder")
|
||||
case utils2.JSONEventFoundBlock:
|
||||
e.PreviousBlocks = append(e.PreviousBlocks, event.FoundBlock)
|
||||
blockFound(e, event.FoundBlock, e.PreviousBlocks.GetPrevious(event.FoundBlock))
|
||||
if len(e.PreviousBlocks) > numberOfBlockHistoryToKeep {
|
||||
//delete oldest block
|
||||
e.PreviousBlocks = slices.Delete(e.PreviousBlocks, 0, 1)
|
||||
}
|
||||
case utils2.JSONEventOrphanedBlock:
|
||||
if i := slices.IndexFunc(e.PreviousBlocks, func(block *index.FoundBlock) bool {
|
||||
return event.SideBlock.MainId == block.MainBlock.Id
|
||||
}); i != -1 {
|
||||
//only notify if we reported it previously
|
||||
slices.Delete(e.PreviousBlocks, i, i+1)
|
||||
blockOrphaned(e, event.SideBlock)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if len(lastBlocks) > 0 {
|
||||
e.LastBlocks = lastBlocks
|
||||
}
|
||||
}
|
||||
}(e)
|
||||
}
|
||||
|
|
8
go.mod
8
go.mod
|
@ -3,17 +3,18 @@ module git.gammaspectra.live/P2Pool/p2pool-observer-bot
|
|||
go 1.20
|
||||
|
||||
require (
|
||||
git.gammaspectra.live/P2Pool/p2pool-observer v0.0.0-20230422082551-fa6e17668bff
|
||||
git.gammaspectra.live/P2Pool/p2pool-observer v0.0.0-20230424175621-2292212ecdc5
|
||||
github.com/whyrusleeping/hellabot v0.0.0-20230331073038-70f5dd5c40d9
|
||||
golang.org/x/exp v0.0.0-20230420155640-133eef4313cb
|
||||
golang.org/x/exp v0.0.0-20230424174712-0ee363d48fb1
|
||||
gopkg.in/inconshreveable/log15.v2 v2.16.0
|
||||
gopkg.in/sorcix/irc.v2 v2.0.0-20200812151606-3f15758ea8c7
|
||||
nhooyr.io/websocket v1.8.7
|
||||
)
|
||||
|
||||
require (
|
||||
filippo.io/edwards25519 v1.0.1-0.20220803165937-8c58ed0e3550 // indirect
|
||||
git.gammaspectra.live/P2Pool/go-monero v0.0.0-20230410011208-910450c4a523 // indirect
|
||||
git.gammaspectra.live/P2Pool/go-randomx v0.0.0-20221025112134-5190471ef823 // indirect
|
||||
git.gammaspectra.live/P2Pool/go-randomx v0.0.0-20221027085532-f46adfce03a7 // indirect
|
||||
git.gammaspectra.live/P2Pool/moneroutil v0.0.0-20221007140323-a2daa2d5fc48 // indirect
|
||||
git.gammaspectra.live/P2Pool/randomx-go-bindings v0.0.0-20221027134633-11f5607e6752 // indirect
|
||||
github.com/bahlo/generic-list-go v0.2.0 // indirect
|
||||
|
@ -23,6 +24,7 @@ require (
|
|||
github.com/holiman/uint256 v1.2.2 // indirect
|
||||
github.com/inconshreveable/log15 v2.16.0+incompatible // indirect
|
||||
github.com/jxskiss/base62 v1.1.0 // indirect
|
||||
github.com/klauspost/compress v1.16.5 // indirect
|
||||
github.com/lib/pq v1.10.8 // indirect
|
||||
github.com/mattn/go-colorable v0.1.13 // indirect
|
||||
github.com/mattn/go-isatty v0.0.18 // indirect
|
||||
|
|
68
go.sum
68
go.sum
|
@ -2,31 +2,65 @@ filippo.io/edwards25519 v1.0.1-0.20220803165937-8c58ed0e3550 h1:Mqu6Q2e//30TWeP5
|
|||
filippo.io/edwards25519 v1.0.1-0.20220803165937-8c58ed0e3550/go.mod h1:N1IkdkCkiLB6tki+MYJoSx2JTY9NUlxZE7eHn5EwJns=
|
||||
git.gammaspectra.live/P2Pool/go-monero v0.0.0-20230410011208-910450c4a523 h1:oIJzm7kQyASS0xlJ79VSWRvvfXp2Qt7M05+E20o9gwE=
|
||||
git.gammaspectra.live/P2Pool/go-monero v0.0.0-20230410011208-910450c4a523/go.mod h1:TAOAAV972JNDkCzyV5SkbYkKCRvcfhvvFa8LHH4Dg6g=
|
||||
git.gammaspectra.live/P2Pool/go-randomx v0.0.0-20221025112134-5190471ef823 h1:HxIuImZsB15Ix59K5VznoHzZ1ut5hW0AAqiDJpOd2+g=
|
||||
git.gammaspectra.live/P2Pool/go-randomx v0.0.0-20221025112134-5190471ef823/go.mod h1:3kT0v4AMwT/OdorfH2gRWPwoOrUX/LV03HEeBsaXG1c=
|
||||
git.gammaspectra.live/P2Pool/go-randomx v0.0.0-20221027085532-f46adfce03a7 h1:bzHDuu1IgETKqPBOlIdCE2LaZIJ+ZpROSprNn+fnzd8=
|
||||
git.gammaspectra.live/P2Pool/go-randomx v0.0.0-20221027085532-f46adfce03a7/go.mod h1:3kT0v4AMwT/OdorfH2gRWPwoOrUX/LV03HEeBsaXG1c=
|
||||
git.gammaspectra.live/P2Pool/moneroutil v0.0.0-20221007140323-a2daa2d5fc48 h1:ExrYG0RSrx/I4McPWgUF4B8R2OkblMrMki2ia8vG6Bw=
|
||||
git.gammaspectra.live/P2Pool/moneroutil v0.0.0-20221007140323-a2daa2d5fc48/go.mod h1:XeSC8jK8RXnnzVAmp9e9AQZCDIbML3UoCRkxxGA+lpU=
|
||||
git.gammaspectra.live/P2Pool/p2pool-observer v0.0.0-20230422082551-fa6e17668bff h1:NLkXWRUgFewD7eqBrmMHTv//lZYCpbRQltTbBAHAyDg=
|
||||
git.gammaspectra.live/P2Pool/p2pool-observer v0.0.0-20230422082551-fa6e17668bff/go.mod h1:tDkKPjbDZK2Ft/HZr/72/wKJ/9wqu8p1ER24WDujc50=
|
||||
git.gammaspectra.live/P2Pool/p2pool-observer v0.0.0-20230424175621-2292212ecdc5 h1:ZjBXaKFlqN/gyQ0y7QLMXYjm1U8y924diBk6TrNMQGI=
|
||||
git.gammaspectra.live/P2Pool/p2pool-observer v0.0.0-20230424175621-2292212ecdc5/go.mod h1:wCBIojZblScPifeE5M+GE1bMumwiDFS5HsMYHIEqTQ8=
|
||||
git.gammaspectra.live/P2Pool/randomx-go-bindings v0.0.0-20221027134633-11f5607e6752 h1:4r4KXpFLbixah+OGrBT9ZEflSZoFHD7aVJpXL3ukVIo=
|
||||
git.gammaspectra.live/P2Pool/randomx-go-bindings v0.0.0-20221027134633-11f5607e6752/go.mod h1:KQaYHIxGXNHNMQELC7xGLu8xouwvP/dN7iGk681BXmk=
|
||||
github.com/bahlo/generic-list-go v0.2.0 h1:5sz/EEAK+ls5wF+NeqDpk5+iNdMDXrh3z3nPnH1Wvgk=
|
||||
github.com/bahlo/generic-list-go v0.2.0/go.mod h1:2KvAjgMlE5NNynlg/5iLrrCCZ2+5xWbdbCW3pNTGyYg=
|
||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/floatdrop/lru v1.3.0 h1:83abtaKjXcWrPmtzTAk2Ggq8DUKqI29YzrTrB8+vu0c=
|
||||
github.com/floatdrop/lru v1.3.0/go.mod h1:83zlXKA06Bm32JImNINCiTr0ldadvdAjUe5jSwIaw0s=
|
||||
github.com/ftrvxmtrx/fd v0.0.0-20150925145434-c6d800382fff h1:zk1wwii7uXmI0znwU+lqg+wFL9G5+vm5I+9rv2let60=
|
||||
github.com/ftrvxmtrx/fd v0.0.0-20150925145434-c6d800382fff/go.mod h1:yUhRXHewUVJ1k89wHKP68xfzk7kwXUx/DV1nx4EBMbw=
|
||||
github.com/gin-contrib/sse v0.1.0 h1:Y/yl/+YNO8GZSjAhjMsSuLt29uWRFHdHYUb5lYOV9qE=
|
||||
github.com/gin-contrib/sse v0.1.0/go.mod h1:RHrZQHXnP2xjPF+u1gW/2HnVO7nvIa9PG3Gm+fLHvGI=
|
||||
github.com/gin-gonic/gin v1.6.3 h1:ahKqKTFpO5KTPHxWZjEdPScmYaGtLo8Y4DMHoEsnp14=
|
||||
github.com/gin-gonic/gin v1.6.3/go.mod h1:75u5sXoLsGZoRN5Sgbi1eraJ4GU3++wFwWzhwvtwp4M=
|
||||
github.com/go-playground/assert/v2 v2.0.1/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4=
|
||||
github.com/go-playground/locales v0.13.0 h1:HyWk6mgj5qFqCT5fjGBuRArbVDfE4hi8+e8ceBS/t7Q=
|
||||
github.com/go-playground/locales v0.13.0/go.mod h1:taPMhCMXrRLJO55olJkUXHZBHCxTMfnGwq/HNwmWNS8=
|
||||
github.com/go-playground/universal-translator v0.17.0 h1:icxd5fm+REJzpZx7ZfpaD876Lmtgy7VtROAbHHXk8no=
|
||||
github.com/go-playground/universal-translator v0.17.0/go.mod h1:UkSxE5sNxxRwHyU+Scu5vgOQjsIJAF8j9muTVoKLVtA=
|
||||
github.com/go-playground/validator/v10 v10.2.0 h1:KgJ0snyC2R9VXYN2rneOtQcw5aHQB1Vv0sFl1UcHBOY=
|
||||
github.com/go-playground/validator/v10 v10.2.0/go.mod h1:uOYAAleCW8F/7oMFd6aG0GOhaH6EGOAJShg8Id5JGkI=
|
||||
github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
|
||||
github.com/go-stack/stack v1.8.1 h1:ntEHSVwIt7PNXNpgPmVfMrNhLtgjlmnZha2kOpuRiDw=
|
||||
github.com/go-stack/stack v1.8.1/go.mod h1:dcoOX6HbPZSZptuspn9bctJ+N/CnF5gGygcUP3XYfe4=
|
||||
github.com/gobwas/httphead v0.0.0-20180130184737-2c6c146eadee h1:s+21KNqlpePfkah2I+gwHF8xmJWRjooY+5248k6m4A0=
|
||||
github.com/gobwas/httphead v0.0.0-20180130184737-2c6c146eadee/go.mod h1:L0fX3K22YWvt/FAX9NnzrNzcI4wNYi9Yku4O0LKYflo=
|
||||
github.com/gobwas/pool v0.2.0 h1:QEmUOlnSjWtnpRGHF3SauEiOsy82Cup83Vf2LcMlnc8=
|
||||
github.com/gobwas/pool v0.2.0/go.mod h1:q8bcK0KcYlCgd9e7WYLm9LpyS+YeLd8JVDW6WezmKEw=
|
||||
github.com/gobwas/ws v1.0.2 h1:CoAavW/wd/kulfZmSIBt6p24n4j7tHgNVCjsfHVNUbo=
|
||||
github.com/gobwas/ws v1.0.2/go.mod h1:szmBTxLgaFppYjEmNtny/v3w89xOydFnnZMcgRRu/EM=
|
||||
github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw=
|
||||
github.com/golang/protobuf v1.3.5 h1:F768QJ1E9tib+q5Sc8MkdJi1RxLTbRcTf8LJV56aRls=
|
||||
github.com/golang/protobuf v1.3.5/go.mod h1:6O5/vntMXwX2lRkT1hjjk0nAC1IDOTvTlVgjlRvqsdk=
|
||||
github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
github.com/google/go-cmp v0.5.8 h1:e6P7q2lk1O+qJJb4BtCQXlK8vWEO8V1ZeuEdJNOqZyg=
|
||||
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
|
||||
github.com/gorilla/websocket v1.4.1 h1:q7AeDBpnBk8AogcD4DSag/Ukw/KV+YhzLj2bP5HvKCM=
|
||||
github.com/gorilla/websocket v1.4.1/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
|
||||
github.com/holiman/uint256 v1.2.2 h1:TXKcSGc2WaxPD2+bmzAsVthL4+pEN0YwXcL5qED83vk=
|
||||
github.com/holiman/uint256 v1.2.2/go.mod h1:SC8Ryt4n+UBbPbIBKaG9zbbDlp4jOru9xFZmPzLUTxw=
|
||||
github.com/inconshreveable/log15 v0.0.0-20200109203555-b30bc20e4fd1/go.mod h1:cOaXtrgN4ScfRrD9Bre7U1thNq5RtJ8ZoP4iXVGRj6o=
|
||||
github.com/inconshreveable/log15 v2.16.0+incompatible h1:6nvMKxtGcpgm7q0KiGs+Vc+xDvUXaBqsPKHWKsinccw=
|
||||
github.com/inconshreveable/log15 v2.16.0+incompatible/go.mod h1:cOaXtrgN4ScfRrD9Bre7U1thNq5RtJ8ZoP4iXVGRj6o=
|
||||
github.com/json-iterator/go v1.1.9 h1:9yzud/Ht36ygwatGx56VwCZtlI/2AD15T1X2sjSuGns=
|
||||
github.com/json-iterator/go v1.1.9/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
|
||||
github.com/jxskiss/base62 v1.1.0 h1:A5zbF8v8WXx2xixnAKD2w+abC+sIzYJX+nxmhA6HWFw=
|
||||
github.com/jxskiss/base62 v1.1.0/go.mod h1:HhWAlUXvxKThfOlZbcuFzsqwtF5TcqS9ru3y5GfjWAc=
|
||||
github.com/klauspost/compress v1.10.3/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs=
|
||||
github.com/klauspost/compress v1.16.5 h1:IFV2oUNUzZaz+XyusxpLzpzS8Pt5rh0Z16For/djlyI=
|
||||
github.com/klauspost/compress v1.16.5/go.mod h1:ntbaceVETuRiXiv4DpjP66DpAtAGkEQskQzEyD//IeE=
|
||||
github.com/leodido/go-urn v1.2.0 h1:hpXL4XnriNwQ/ABnpepYM/1vCLWNDfUNts8dX3xTG6Y=
|
||||
github.com/leodido/go-urn v1.2.0/go.mod h1:+8+nEpDfqqsY+g338gtMEUOtuK+4dEMhiQEgxpxOKII=
|
||||
github.com/lib/pq v1.10.8 h1:3fdt97i/cwSU83+E0hZTC/Xpc9mTZxc6UWSCRcSbxiE=
|
||||
github.com/lib/pq v1.10.8/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o=
|
||||
github.com/mattn/go-colorable v0.1.6/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc=
|
||||
|
@ -36,15 +70,27 @@ github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Ky
|
|||
github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM=
|
||||
github.com/mattn/go-isatty v0.0.18 h1:DOKFKCQ7FNG2L1rbrmstDN4QVRdS89Nkh85u68Uwp98=
|
||||
github.com/mattn/go-isatty v0.0.18/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
|
||||
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421 h1:ZqeYNhU3OHLH3mGKHDcjJRFFRrJa6eAM5H+CtDdOsPc=
|
||||
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
|
||||
github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742 h1:Esafd1046DLDQ0W1YjYsBW+p8U2u7vzgW2SQVmlNazg=
|
||||
github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
|
||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
github.com/sclevine/spec v1.4.0 h1:z/Q9idDcay5m5irkZ28M7PtQM4aOISzOpj4bUPkDee8=
|
||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
|
||||
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
|
||||
github.com/stretchr/testify v1.8.1 h1:w7B6lhMri9wdJUVmEZPGGhZzrYTPvgJArz7wNPgYKsk=
|
||||
github.com/ugorji/go v1.1.7 h1:/68gy2h+1mWMrwZFeD1kQialdSzAb432dtpeJ42ovdo=
|
||||
github.com/ugorji/go v1.1.7/go.mod h1:kZn38zHttfInRq0xu/PH0az30d+z6vm202qpg1oXVMw=
|
||||
github.com/ugorji/go/codec v1.1.7 h1:2SvQaVZ1ouYrrKKwoSk2pzd4A9evlKJb9oTL+OaLUSs=
|
||||
github.com/ugorji/go/codec v1.1.7/go.mod h1:Ax+UKWsSmolVDwsd+7N3ZtXu+yMGCf907BLYF3GoBXY=
|
||||
github.com/whyrusleeping/hellabot v0.0.0-20230331073038-70f5dd5c40d9 h1:y7lb+uda1qXXCfyxbPV707hHWrPL5bfId2bk7n9kvm8=
|
||||
github.com/whyrusleeping/hellabot v0.0.0-20230331073038-70f5dd5c40d9/go.mod h1:g3f61CcN5csyM0R/e0xF2FX8gKiuGHREi3ostG6FWlQ=
|
||||
golang.org/x/crypto v0.8.0 h1:pd9TJtTueMTVQXzk8E2XESSMQDj/U7OUu0PqJqPXQjQ=
|
||||
golang.org/x/crypto v0.8.0/go.mod h1:mRqEX+O9/h5TFCrQhkgjo2yKi0yYA+9ecGkdQoHrywE=
|
||||
golang.org/x/exp v0.0.0-20230420155640-133eef4313cb h1:rhjz/8Mbfa8xROFiH+MQphmAmgqRM0bOMnytznhWEXk=
|
||||
golang.org/x/exp v0.0.0-20230420155640-133eef4313cb/go.mod h1:V1LtkGg67GoY2N1AnLN78QLrzxkLyJw7RJb1gzOOz9w=
|
||||
golang.org/x/exp v0.0.0-20230424174712-0ee363d48fb1 h1:7ewEue0BB5yqldKyRBV5KoDD2uiBiQpTA6DxObvjj/M=
|
||||
golang.org/x/exp v0.0.0-20230424174712-0ee363d48fb1/go.mod h1:V1LtkGg67GoY2N1AnLN78QLrzxkLyJw7RJb1gzOOz9w=
|
||||
golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
|
@ -53,11 +99,21 @@ golang.org/x/sys v0.7.0 h1:3jlCCIQZPdOYu1h8BkNvLz8Kgwtae2cagcG/VamtZRU=
|
|||
golang.org/x/sys v0.7.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/term v0.7.0 h1:BEvjmm5fURWqcfbSKTdpkDXYBrUS1c0m8agp14W48vQ=
|
||||
golang.org/x/term v0.7.0/go.mod h1:P32HKFT3hSsZrRxla30E9HqToFYAQPCMs/zFMBUFqPY=
|
||||
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
|
||||
golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/inconshreveable/log15.v2 v2.0.0-20200109203555-b30bc20e4fd1/go.mod h1:aPpfJ7XW+gOuirDoZ8gHhLh3kZ1B08FtV2bbmy7Jv3s=
|
||||
gopkg.in/inconshreveable/log15.v2 v2.16.0 h1:LWHLVX8KbBMkQFSqfno4901Z4Wg8L3B7Cu0n4K/Q7MA=
|
||||
gopkg.in/inconshreveable/log15.v2 v2.16.0/go.mod h1:aPpfJ7XW+gOuirDoZ8gHhLh3kZ1B08FtV2bbmy7Jv3s=
|
||||
gopkg.in/sorcix/irc.v2 v2.0.0-20200812151606-3f15758ea8c7 h1:XS4tmz0w7EYviIrBpFVww8IyKJQiIX5SU/1ptPVtBWI=
|
||||
gopkg.in/sorcix/irc.v2 v2.0.0-20200812151606-3f15758ea8c7/go.mod h1:PmJkUcwbuPi1FiZ9Rarr6wzVMvzkO7uWqH1jwrMkgW0=
|
||||
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.2.8 h1:obN1ZagJSUGI0Ek/LBmuj4SNLPfIny3KsKFopxRdj10=
|
||||
gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
||||
lukechampine.com/uint128 v1.3.0 h1:cDdUVfRwDUDovz610ABgFD17nXD4/uDgVHl2sC3+sbo=
|
||||
lukechampine.com/uint128 v1.3.0/go.mod h1:c4eWIwlEGaxC/+H1VguhU4PHXNWDCDMUlWdIWl2j1gk=
|
||||
nhooyr.io/websocket v1.8.7 h1:usjR2uOr/zjjkVMy0lW+PPohFok7PCow5sDjLgX4P4g=
|
||||
nhooyr.io/websocket v1.8.7/go.mod h1:B70DZP8IakI65RVQ51MsWP/8jndNma26DVA/nFSCgW0=
|
||||
|
|
Loading…
Reference in a new issue