Skip to content

Commit 3eedb36

Browse files
authored
Merge pull request #77 from InjectiveLabs/master
v1.9.1
2 parents ade8906 + 228fa42 commit 3eedb36

File tree

5 files changed

+186
-27
lines changed

5 files changed

+186
-27
lines changed

cmd/peggo/orchestrator.go

Lines changed: 28 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -220,6 +220,14 @@ func orchestratorCmd(cmd *cli.Cmd) {
220220
peggyAddress := ethcmn.HexToAddress(peggyParams.BridgeEthereumAddress)
221221
injAddress := ethcmn.HexToAddress(peggyParams.CosmosCoinErc20Contract)
222222

223+
// Check if the provided ETH address belongs to a validator
224+
isValidator, err := isValidatorAddress(cosmosQueryClient, ethKeyFromAddress)
225+
if err != nil {
226+
log.WithError(err).Fatalln("failed to query the current validator set from injective")
227+
228+
return
229+
}
230+
223231
erc20ContractMapping := make(map[ethcmn.Address]string)
224232
erc20ContractMapping[injAddress] = ctypes.InjectiveCoin
225233

@@ -269,7 +277,7 @@ func orchestratorCmd(cmd *cli.Cmd) {
269277
)
270278

271279
go func() {
272-
if err := svc.Start(ctx); err != nil {
280+
if err := svc.Start(ctx, isValidator); err != nil {
273281
log.Errorln(err)
274282

275283
// signal there that the app failed
@@ -280,3 +288,22 @@ func orchestratorCmd(cmd *cli.Cmd) {
280288
closer.Hold()
281289
}
282290
}
291+
292+
func isValidatorAddress(peggyQuery cosmos.PeggyQueryClient, addr ethcmn.Address) (bool, error) {
293+
ctx, cancelFn := context.WithTimeout(context.Background(), time.Second*30)
294+
defer cancelFn()
295+
296+
currentValset, err := peggyQuery.CurrentValset(ctx)
297+
if err != nil {
298+
return false, err
299+
}
300+
301+
var isValidator bool
302+
for _, validator := range currentValset.Members {
303+
if ethcmn.HexToAddress(validator.EthereumAddress) == addr {
304+
isValidator = true
305+
}
306+
}
307+
308+
return isValidator, nil
309+
}

orchestrator/cosmos/broadcast.go

Lines changed: 59 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ import (
1414
chainclient "github.com/InjectiveLabs/sdk-go/client/chain"
1515

1616
"github.com/InjectiveLabs/metrics"
17+
1718
"github.com/InjectiveLabs/peggo/orchestrator/ethereum/keystore"
1819
"github.com/InjectiveLabs/peggo/orchestrator/ethereum/peggy"
1920

@@ -55,6 +56,7 @@ type PeggyBroadcastClient interface {
5556
oldDeposits []*wrappers.PeggySendToCosmosEvent,
5657
deposits []*wrappers.PeggySendToInjectiveEvent,
5758
withdraws []*wrappers.PeggyTransactionBatchExecutedEvent,
59+
erc20Deployed []*wrappers.PeggyERC20DeployedEvent,
5860
valsetUpdates []*wrappers.PeggyValsetUpdatedEvent,
5961
) error
6062

@@ -274,7 +276,7 @@ func (s *peggyBroadcastClient) sendOldDepositClaims(
274276
log.WithFields(log.Fields{
275277
"event_nonce": oldDeposit.EventNonce.String(),
276278
"txHash": txResponse.TxResponse.TxHash,
277-
}).Infoln("Oracle sent old deposit event succesfully")
279+
}).Infoln("Oracle sent old deposit event successfully")
278280
}
279281

280282
return nil
@@ -320,7 +322,7 @@ func (s *peggyBroadcastClient) sendDepositClaims(
320322
log.WithFields(log.Fields{
321323
"event_nonce": deposit.EventNonce.String(),
322324
"txHash": txResponse.TxResponse.TxHash,
323-
}).Infoln("Oracle sent deposit event succesfully")
325+
}).Infoln("Oracle sent deposit event successfully")
324326
}
325327

326328
return nil
@@ -358,7 +360,7 @@ func (s *peggyBroadcastClient) sendWithdrawClaims(
358360
log.WithFields(log.Fields{
359361
"event_nonce": withdraw.EventNonce.String(),
360362
"txHash": txResponse.TxResponse.TxHash,
361-
}).Infoln("Oracle sent Withdraw event succesfully")
363+
}).Infoln("Oracle sent Withdraw event successfully")
362364
}
363365

364366
return nil
@@ -407,7 +409,49 @@ func (s *peggyBroadcastClient) sendValsetUpdateClaims(
407409
log.WithFields(log.Fields{
408410
"event_nonce": valsetUpdate.EventNonce.String(),
409411
"txHash": txResponse.TxResponse.TxHash,
410-
}).Infoln("Oracle sent ValsetUpdate event succesfully")
412+
}).Infoln("Oracle sent ValsetUpdate event successfully")
413+
}
414+
415+
return nil
416+
}
417+
418+
func (s *peggyBroadcastClient) sendErc20DeployedClaims(
419+
ctx context.Context,
420+
erc20Deployed *wrappers.PeggyERC20DeployedEvent,
421+
) error {
422+
metrics.ReportFuncCall(s.svcTags)
423+
doneFn := metrics.ReportFuncTiming(s.svcTags)
424+
defer doneFn()
425+
426+
log.WithFields(log.Fields{
427+
"EventNonce": erc20Deployed.EventNonce.Uint64(),
428+
"CosmosDenom": erc20Deployed.CosmosDenom,
429+
"TokenContract": erc20Deployed.TokenContract.Hex(),
430+
"Name": erc20Deployed.Name,
431+
"Symbol": erc20Deployed.Symbol,
432+
"Decimals": erc20Deployed.Decimals,
433+
}).Infoln("Oracle observed a erc20Deployed event. Sending MsgERC20DeployedClaim")
434+
435+
msg := &types.MsgERC20DeployedClaim{
436+
EventNonce: erc20Deployed.EventNonce.Uint64(),
437+
BlockHeight: erc20Deployed.Raw.BlockNumber,
438+
CosmosDenom: erc20Deployed.CosmosDenom,
439+
TokenContract: erc20Deployed.TokenContract.Hex(),
440+
Name: erc20Deployed.Name,
441+
Symbol: erc20Deployed.Symbol,
442+
Decimals: uint64(erc20Deployed.Decimals),
443+
Orchestrator: s.AccFromAddress().String(),
444+
}
445+
446+
if txResponse, err := s.broadcastClient.SyncBroadcastMsg(msg); err != nil {
447+
metrics.ReportFuncError(s.svcTags)
448+
log.WithError(err).Errorln("broadcasting MsgERC20DeployedClaim failed")
449+
return err
450+
} else {
451+
log.WithFields(log.Fields{
452+
"event_nonce": erc20Deployed.EventNonce.String(),
453+
"txHash": txResponse.TxResponse.TxHash,
454+
}).Infoln("Oracle sent ERC20DeployedEvent event successfully")
411455
}
412456

413457
return nil
@@ -419,14 +463,15 @@ func (s *peggyBroadcastClient) SendEthereumClaims(
419463
oldDeposits []*wrappers.PeggySendToCosmosEvent,
420464
deposits []*wrappers.PeggySendToInjectiveEvent,
421465
withdraws []*wrappers.PeggyTransactionBatchExecutedEvent,
466+
erc20Deployed []*wrappers.PeggyERC20DeployedEvent,
422467
valsetUpdates []*wrappers.PeggyValsetUpdatedEvent,
423468
) error {
424469
metrics.ReportFuncCall(s.svcTags)
425470
doneFn := metrics.ReportFuncTiming(s.svcTags)
426471
defer doneFn()
427472

428-
totalClaimEvents := len(oldDeposits) + len(deposits) + len(withdraws) + len(valsetUpdates)
429-
var count, h, i, j, k int
473+
totalClaimEvents := len(oldDeposits) + len(deposits) + len(withdraws) + len(erc20Deployed) + len(valsetUpdates)
474+
var count, h, i, j, k, l int
430475

431476
// Individual arrays (oldDeposits, deposits, withdraws, valsetUpdates) are sorted.
432477
// Broadcast claim events sequentially starting with eventNonce = lastClaimEvent + 1.
@@ -464,6 +509,14 @@ func (s *peggyBroadcastClient) SendEthereumClaims(
464509
return err
465510
}
466511
k++
512+
} else if l < len(erc20Deployed) && erc20Deployed[l].EventNonce.Uint64() == lastClaimEvent+1 {
513+
// send erc20 deployed claim
514+
if err := s.sendErc20DeployedClaims(ctx, erc20Deployed[l]); err != nil {
515+
metrics.ReportFuncError(s.svcTags)
516+
log.WithError(err).Errorln("broadcasting MsgERC20DeployedClaim failed")
517+
return err
518+
}
519+
l++
467520
}
468521
count = count + 1
469522
lastClaimEvent = lastClaimEvent + 1

orchestrator/eth_event_watcher.go

Lines changed: 53 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import (
99
log "github.com/xlab/suplog"
1010

1111
"github.com/InjectiveLabs/metrics"
12+
1213
wrappers "github.com/InjectiveLabs/peggo/solidity/wrappers/Peggy.sol"
1314
)
1415

@@ -157,6 +158,39 @@ func (s *peggyOrchestrator) CheckForEvents(
157158
"Withdraws": transactionBatchExecutedEvents,
158159
}).Debugln("Scanned TransactionBatchExecuted events from Ethereum")
159160

161+
var erc20DeployedEvents []*wrappers.PeggyERC20DeployedEvent
162+
{
163+
iter, err := peggyFilterer.FilterERC20DeployedEvent(&bind.FilterOpts{
164+
Start: startingBlock,
165+
End: &currentBlock,
166+
}, nil)
167+
if err != nil {
168+
metrics.ReportFuncError(s.svcTags)
169+
log.WithFields(log.Fields{
170+
"start": startingBlock,
171+
"end": currentBlock,
172+
}).Errorln("failed to scan past FilterERC20Deployed events from Ethereum")
173+
174+
if !isUnknownBlockErr(err) {
175+
err = errors.Wrap(err, "failed to scan past FilterERC20Deployed events from Ethereum")
176+
return 0, err
177+
} else if iter == nil {
178+
return 0, errors.New("no iterator returned")
179+
}
180+
}
181+
182+
for iter.Next() {
183+
erc20DeployedEvents = append(erc20DeployedEvents, iter.Event)
184+
}
185+
186+
iter.Close()
187+
}
188+
log.WithFields(log.Fields{
189+
"start": startingBlock,
190+
"end": currentBlock,
191+
"erc20Deployed": erc20DeployedEvents,
192+
}).Debugln("Scanned FilterERC20Deployed events from Ethereum")
193+
160194
var valsetUpdatedEvents []*wrappers.PeggyValsetUpdatedEvent
161195
{
162196
iter, err := peggyFilterer.FilterValsetUpdatedEvent(&bind.FilterOpts{
@@ -191,7 +225,7 @@ func (s *peggyOrchestrator) CheckForEvents(
191225
"valsetUpdates": valsetUpdatedEvents,
192226
}).Debugln("Scanned ValsetUpdatedEvents events from Ethereum")
193227

194-
// note that starting block overlaps with our last che cked block, because we have to deal with
228+
// note that starting block overlaps with our last checked block, because we have to deal with
195229
// the possibility that the relayer was killed after relaying only one of multiple events in a single
196230
// block, so we also need this routine so make sure we don't send in the first event in this hypothetical
197231
// multi event block again. In theory we only send all events for every block and that will pass of fail
@@ -206,11 +240,12 @@ func (s *peggyOrchestrator) CheckForEvents(
206240
oldDeposits := filterSendToCosmosEventsByNonce(sendToCosmosEvents, lastClaimEvent.EthereumEventNonce)
207241
deposits := filterSendToInjectiveEventsByNonce(sendToInjectiveEvents, lastClaimEvent.EthereumEventNonce)
208242
withdraws := filterTransactionBatchExecutedEventsByNonce(transactionBatchExecutedEvents, lastClaimEvent.EthereumEventNonce)
243+
erc20Deployments := filterERC20DeployedEventsByNonce(erc20DeployedEvents, lastClaimEvent.EthereumEventNonce)
209244
valsetUpdates := filterValsetUpdateEventsByNonce(valsetUpdatedEvents, lastClaimEvent.EthereumEventNonce)
210245

211-
if len(oldDeposits) > 0 || len(deposits) > 0 || len(withdraws) > 0 || len(valsetUpdates) > 0 {
246+
if len(oldDeposits) > 0 || len(deposits) > 0 || len(withdraws) > 0 || len(erc20Deployments) > 0 || len(valsetUpdates) > 0 {
212247
// todo get eth chain id from the chain
213-
if err := s.peggyBroadcastClient.SendEthereumClaims(ctx, lastClaimEvent.EthereumEventNonce, oldDeposits, deposits, withdraws, valsetUpdates); err != nil {
248+
if err := s.peggyBroadcastClient.SendEthereumClaims(ctx, lastClaimEvent.EthereumEventNonce, oldDeposits, deposits, withdraws, erc20Deployments, valsetUpdates); err != nil {
214249
metrics.ReportFuncError(s.svcTags)
215250
err = errors.Wrap(err, "failed to send ethereum claims to Cosmos chain")
216251
return 0, err
@@ -265,6 +300,21 @@ func filterTransactionBatchExecutedEventsByNonce(
265300
return res
266301
}
267302

303+
func filterERC20DeployedEventsByNonce(
304+
events []*wrappers.PeggyERC20DeployedEvent,
305+
nonce uint64,
306+
) []*wrappers.PeggyERC20DeployedEvent {
307+
res := make([]*wrappers.PeggyERC20DeployedEvent, 0, len(events))
308+
309+
for _, ev := range events {
310+
if ev.EventNonce.Uint64() > nonce {
311+
res = append(res, ev)
312+
}
313+
}
314+
315+
return res
316+
}
317+
268318
func filterValsetUpdateEventsByNonce(
269319
events []*wrappers.PeggyValsetUpdatedEvent,
270320
nonce uint64,

orchestrator/main_loops.go

Lines changed: 45 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -25,23 +25,14 @@ const defaultLoopDur = 60 * time.Second
2525

2626
// Start combines the all major roles required to make
2727
// up the Orchestrator, all of these are async loops.
28-
func (s *peggyOrchestrator) Start(ctx context.Context) error {
29-
var pg loops.ParanoidGroup
30-
31-
pg.Go(func() error {
32-
return s.EthOracleMainLoop(ctx)
33-
})
34-
pg.Go(func() error {
35-
return s.BatchRequesterLoop(ctx)
36-
})
37-
pg.Go(func() error {
38-
return s.EthSignerMainLoop(ctx)
39-
})
40-
pg.Go(func() error {
41-
return s.RelayerMainLoop(ctx)
42-
})
28+
func (s *peggyOrchestrator) Start(ctx context.Context, validatorMode bool) error {
29+
if !validatorMode {
30+
log.Infoln("Starting peggo in relayer (non-validator) mode")
31+
return s.startRelayerMode(ctx)
32+
}
4333

44-
return pg.Wait()
34+
log.Infoln("Starting peggo in validator mode")
35+
return s.startValidatorMode(ctx)
4536
}
4637

4738
// EthOracleMainLoop is responsible for making sure that Ethereum events are retrieved from the Ethereum blockchain
@@ -395,3 +386,41 @@ func calculateTotalValsetPower(valset *types.Valset) *big.Int {
395386

396387
return totalValsetPower
397388
}
389+
390+
// startValidatorMode runs all orchestrator processes. This is called
391+
// when peggo is run alongside a validator injective node.
392+
func (s *peggyOrchestrator) startValidatorMode(ctx context.Context) error {
393+
var pg loops.ParanoidGroup
394+
395+
pg.Go(func() error {
396+
return s.EthOracleMainLoop(ctx)
397+
})
398+
pg.Go(func() error {
399+
return s.BatchRequesterLoop(ctx)
400+
})
401+
pg.Go(func() error {
402+
return s.EthSignerMainLoop(ctx)
403+
})
404+
pg.Go(func() error {
405+
return s.RelayerMainLoop(ctx)
406+
})
407+
408+
return pg.Wait()
409+
}
410+
411+
// startRelayerMode runs orchestrator processes that only relay specific
412+
// messages that do not require a validator's signature. This mode is run
413+
// alongside a non-validator injective node
414+
func (s *peggyOrchestrator) startRelayerMode(ctx context.Context) error {
415+
var pg loops.ParanoidGroup
416+
417+
pg.Go(func() error {
418+
return s.BatchRequesterLoop(ctx)
419+
})
420+
421+
pg.Go(func() error {
422+
return s.RelayerMainLoop(ctx)
423+
})
424+
425+
return pg.Wait()
426+
}

orchestrator/orchestrator.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ import (
1717
)
1818

1919
type PeggyOrchestrator interface {
20-
Start(ctx context.Context) error
20+
Start(ctx context.Context, validatorMode bool) error
2121

2222
CheckForEvents(ctx context.Context, startingBlock uint64) (currentBlock uint64, err error)
2323
GetLastCheckedBlock(ctx context.Context) (uint64, error)

0 commit comments

Comments
 (0)