diff options
Diffstat (limited to 'monitor/monitor.go')
-rw-r--r-- | monitor/monitor.go | 199 |
1 files changed, 199 insertions, 0 deletions
diff --git a/monitor/monitor.go b/monitor/monitor.go new file mode 100644 index 0000000..5b9e350 --- /dev/null +++ b/monitor/monitor.go @@ -0,0 +1,199 @@ +package monitor + +import ( + "log" + "math" + "math/big" + "strconv" + "time" + + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/ethclient" +) + +type node struct { + owner common.Address + email string + fined *big.Int + name string + publicKey []byte + nodeKeyAddress common.Address +} + +// NetworkConfig represents the network config. +type NetworkConfig struct { + WSEndpoint string + HTTPEndpoint string + EthHTTPEndpoint string + GovAddress common.Address + Network string +} + +// GovAddress is governance address. +var GovAddress = common.HexToAddress("0x246FcDE58581e2754f215A523C0718C4BFc8041F") + +// Fifty is 50 * 10^18 +var Fifty *big.Int + +// OneHundred is 100 * 10^18 +var OneHundred *big.Int + +func init() { + Fifty, _ = big.NewInt(0).SetString("50000000000000000000", 10) + OneHundred, _ = big.NewInt(0).SetString("100000000000000000000", 10) +} + +// NetworkConfigMap represents the system network config mapping. +var NetworkConfigMap = map[int64]NetworkConfig{ + 373: { + WSEndpoint: "wss://mainnet-rpc.tangerine-network.io/ws", + HTTPEndpoint: "https://mainnet-rpc.tangerine-network.io", + EthHTTPEndpoint: "https://mainnet.infura.io/v3/4eb07139b29d41c59b352f21c4c9f526", + Network: "Mainnet", + }, + 374: { + WSEndpoint: "wss://testnet-rpc.tangerine-network.io/ws", + HTTPEndpoint: "https://testnet-rpc.tangerine-network.io", + EthHTTPEndpoint: "https://rinkeby.infura.io/v3/4eb07139b29d41c59b352f21c4c9f526", + Network: "Testnet", + }, +} + +// Monitor is the object to monitor tangerine network. +type Monitor struct { + networkID int + notifiers []Notifier + backend backendIntf + tanBalancesCache map[common.Address]*big.Int + ethBalancesCache map[common.Address]*big.Int + ethThreshold *big.Int // in wei + ethThresholdString string // in ETH + checkBalanceDuration time.Duration +} + +// NewMonitor is the constructor for monitor object. +func NewMonitor(networkID int, backend backendIntf, threshold string) *Monitor { + tanBalance := make(map[common.Address]*big.Int) + ethBalance := make(map[common.Address]*big.Int) + t, err := strconv.ParseFloat(threshold, 64) + if err != nil { + panic(err) + } + t = t * math.Pow(10, 18) + ethThreshold := new(big.Int) + ethThreshold.SetString( + strconv.FormatFloat(t, 'f', 0, 64), + 10, + ) + m := Monitor{ + networkID: networkID, + backend: backend, + tanBalancesCache: tanBalance, + ethBalancesCache: ethBalance, + checkBalanceDuration: time.Duration(10 * 60 * 1000 * 1000 * 1000), + ethThresholdString: threshold, + ethThreshold: ethThreshold, + } + return &m +} + +// Run is the entry point for running monitor. +func (m *Monitor) Run() { + done := make(chan bool) + finedNodeChan := make(chan node) + go m.fetchFinedNodes(finedNodeChan) + go m.sendNotifications(finedNodeChan, FINED) + go m.checkTanBalance() + go m.checkEthBalance() + <-done +} + +func (m *Monitor) checkEthBalance() { + ethNodeChan := make(chan node) + go m.sendNotifications(ethNodeChan, INSUFFICIENT_ETH) + for { + nc := NetworkConfigMap[int64(m.networkID)] + conn, err := ethclient.Dial(nc.EthHTTPEndpoint) + if err != nil { + log.Println("Get Tan balance fail at") + continue + } + nodes := m.backend.NodeSet() + for i := range nodes { + n := nodes[i] + address := n.nodeKeyAddress + balance := m.backend.BalanceFromAddress(conn, address) + if balance.Cmp(m.ethThreshold) < 0 { + if cacheBalance, exist := m.ethBalancesCache[address]; exist { + if cacheBalance.Cmp(m.ethThreshold) >= 0 { + ethNodeChan <- n + } + } else { + ethNodeChan <- n + } + } + m.ethBalancesCache[address] = balance + } + time.Sleep(m.checkBalanceDuration) + } +} + +func (m *Monitor) checkTanBalance() { + tanNodeChan := make(chan node) + go m.sendNotifications(tanNodeChan, INSUFFICIENT_TAN) + for { + nodes := m.backend.NodeSet() + nc := NetworkConfigMap[int64(m.networkID)] + conn, err := ethclient.Dial(nc.HTTPEndpoint) + if err != nil { + log.Println("Get Eth balance fail") + continue + } + for i := range nodes { + n := nodes[i] + balance := m.backend.BalanceFromAddress(conn, n.nodeKeyAddress) + if balance.Cmp(Fifty) < 0 { + if cacheBalance, exist := m.tanBalancesCache[n.nodeKeyAddress]; exist { + if cacheBalance.Cmp(Fifty) >= 0 { + tanNodeChan <- n + } + } else { + tanNodeChan <- n + } + } else if balance.Cmp(OneHundred) < 0 { + if cacheBalance, exist := m.tanBalancesCache[n.nodeKeyAddress]; exist { + if cacheBalance.Cmp(OneHundred) >= 0 { + tanNodeChan <- n + } + } else { + tanNodeChan <- n + } + } + m.tanBalancesCache[n.nodeKeyAddress] = balance + } + time.Sleep(m.checkBalanceDuration) + } +} + +// Register registries the notifiers. +func (m *Monitor) Register(n Notifier) { + m.notifiers = append(m.notifiers, n) +} + +func (m *Monitor) fetchFinedNodes(nodeChan chan node) { + m.backend.FetchFinedNodes(nodeChan) +} + +func (m *Monitor) sendNotifications(nodeChan chan node, notifyType uint) { + nc := NetworkConfigMap[int64(m.networkID)] + for { + node, open := <-nodeChan + if !open { + return + } + for _, notifier := range m.notifiers { + notifier.notify(node, nc.Network, + notifyType, m.ethThresholdString) + } + } +} |