-
Notifications
You must be signed in to change notification settings - Fork 5
/
chain.go
164 lines (145 loc) · 3.84 KB
/
chain.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
package chains
import (
"context"
"fmt"
"sync"
"time"
"github.com/celer-network/endpoint-proxy/endpointproxy"
"github.com/celer-network/goutils/eth/mon2"
"github.com/celer-network/goutils/log"
"github.com/celer-network/im-executor/contracts"
"github.com/celer-network/im-executor/dal"
"github.com/celer-network/im-executor/sgn-v2/eth"
"github.com/ethereum/go-ethereum/ethclient"
"github.com/spf13/viper"
)
type Chain struct {
*OneChainConfig
*Contracts
EthClient *ethclient.Client
monitor2 *mon2.Monitor
balAlertCtl chan bool
}
type Chains struct {
// chainid => Chain
chains map[uint64]*Chain
lock sync.RWMutex
initWg sync.WaitGroup
}
var chains *Chains
func InitChains() *Chains {
chains = NewChains()
return chains
}
func NewChains() *Chains {
log.Infoln("Initializing chains")
var configs []*OneChainConfig
err := viper.UnmarshalKey(FlagMultiChain, &configs)
if err != nil {
log.Fatalf("failed to load multichain configs:%v", err)
return nil
}
cs := &Chains{chains: make(map[uint64]*Chain)}
for _, config := range configs {
cs.initWg.Add(1)
go cs.addChain(config)
}
cs.initWg.Wait()
log.Infoln("Finished initializing all chains")
return cs
}
func (c *Chains) addChain(config *OneChainConfig) {
ec := newEthClient(config)
// init monitor
chainConfig := mon2.PerChainCfg{
BlkIntv: time.Duration(config.BlkInterval) * time.Second,
BlkDelay: config.BlkDelay,
MaxBlkDelta: config.MaxBlkDelta,
ForwardBlkDelay: config.ForwardBlkDelay,
}
db := dal.GetDB()
mon, err := mon2.NewMonitor(ec, db, chainConfig)
if err != nil {
log.Fatalln("failed to create monitor: ", err)
}
chain := &Chain{
OneChainConfig: config,
Contracts: NewContracts(ec, config),
EthClient: ec,
monitor2: mon,
balAlertCtl: make(chan bool),
}
c.lock.Lock()
defer func() {
c.lock.Unlock()
c.initWg.Done()
}()
c.chains[chain.ChainID] = chain
}
func (c *Chains) GetChain(chid uint64) (*Chain, bool) {
c.lock.RLock()
defer c.lock.RUnlock()
chain, ok := c.chains[chid]
return chain, ok
}
func GetChain(chid uint64) (*Chain, bool) {
return chains.GetChain(chid)
}
func GetChainMustExist(chid uint64) *Chain {
chain, ok := chains.GetChain(chid)
if !ok {
log.Panicf("chain %d not found", chid)
}
return chain
}
func StartMonitoring(filters contracts.ReceiverContracts, signers map[uint64][]eth.Addr) {
for _, chain := range chains.chains {
go chain.startMonitoringEvents(filters)
go chain.startMonitoringBalance(signers[chain.ChainID])
}
}
func StopMonitoring() {
for _, chain := range chains.chains {
chain.monitor2.Close()
close(chain.balAlertCtl)
}
}
func ReloadConfig() error {
cs := NewChains()
chains.lock.Lock()
defer chains.lock.Unlock()
chains.chains = cs.chains
return nil
}
func newEthClient(config *OneChainConfig) *ethclient.Client {
// init eth client
log.Infof("Dialing eth client for chain %d at %s", config.ChainID, config.Gateway)
var ec *ethclient.Client
var err error
if config.ProxyPort > 0 {
proxyPort := config.ProxyPort
if err = endpointproxy.StartProxy(config.Gateway, config.ChainID, proxyPort); err != nil {
log.Fatalln("can not start proxy for chain:", config.ChainID, "gateway:", config.Gateway, "port:", proxyPort, "err:", err)
}
ec, err = ethclient.Dial(fmt.Sprintf("http://127.0.0.1:%d", proxyPort))
if err != nil {
log.Fatalln("dial", config.Gateway, "err:", err)
}
} else {
ec, err = ethclient.Dial(config.Gateway)
if err != nil {
log.Fatalln("dial", config.Gateway, "err:", err)
}
}
checkChainID(ec, config.ChainID)
return ec
}
func checkChainID(ec *ethclient.Client, chainID uint64) {
chid, err := ec.ChainID(context.Background())
if err != nil {
log.Fatalf("get chainid %d err: %s", chainID, err)
}
if chid.Uint64() != chainID {
log.Fatalf("chainid mismatch! chainConf has %d but onchain has %d", chainID, chid.Uint64())
}
}