node: terra reobservation
This commit is contained in:
parent
7220f4d598
commit
9ed71c0038
|
@ -540,6 +540,7 @@ func runNode(cmd *cobra.Command, args []string) {
|
|||
// Observation request channel for each chain supporting observation requests.
|
||||
chainObsvReqC[vaa.ChainIDSolana] = make(chan *gossipv1.ObservationRequest)
|
||||
chainObsvReqC[vaa.ChainIDEthereum] = make(chan *gossipv1.ObservationRequest)
|
||||
chainObsvReqC[vaa.ChainIDTerra] = make(chan *gossipv1.ObservationRequest)
|
||||
chainObsvReqC[vaa.ChainIDBSC] = make(chan *gossipv1.ObservationRequest)
|
||||
chainObsvReqC[vaa.ChainIDPolygon] = make(chan *gossipv1.ObservationRequest)
|
||||
chainObsvReqC[vaa.ChainIDAvalanche] = make(chan *gossipv1.ObservationRequest)
|
||||
|
@ -694,7 +695,7 @@ func runNode(cmd *cobra.Command, args []string) {
|
|||
// Start Terra watcher only if configured
|
||||
logger.Info("Starting Terra watcher")
|
||||
if err := supervisor.Run(ctx, "terrawatch",
|
||||
terra.NewWatcher(*terraWS, *terraLCD, *terraContract, lockC, setC).Run); err != nil {
|
||||
terra.NewWatcher(*terraWS, *terraLCD, *terraContract, lockC, setC, chainObsvReqC[vaa.ChainIDTerra]).Run); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
|
|
|
@ -35,6 +35,10 @@ type (
|
|||
|
||||
msgChan chan *common.MessagePublication
|
||||
setChan chan *common.GuardianSet
|
||||
|
||||
// Incoming re-observation requests from the network. Pre-filtered to only
|
||||
// include requests for our chainID.
|
||||
obsvReqC chan *gossipv1.ObservationRequest
|
||||
}
|
||||
)
|
||||
|
||||
|
@ -73,8 +77,14 @@ type clientRequest struct {
|
|||
}
|
||||
|
||||
// NewWatcher creates a new Terra contract watcher
|
||||
func NewWatcher(urlWS string, urlLCD string, contract string, lockEvents chan *common.MessagePublication, setEvents chan *common.GuardianSet) *Watcher {
|
||||
return &Watcher{urlWS: urlWS, urlLCD: urlLCD, contract: contract, msgChan: lockEvents, setChan: setEvents}
|
||||
func NewWatcher(
|
||||
urlWS string,
|
||||
urlLCD string,
|
||||
contract string,
|
||||
lockEvents chan *common.MessagePublication,
|
||||
setEvents chan *common.GuardianSet,
|
||||
obsvReqC chan *gossipv1.ObservationRequest) *Watcher {
|
||||
return &Watcher{urlWS: urlWS, urlLCD: urlLCD, contract: contract, msgChan: lockEvents, setChan: setEvents, obsvReqC: obsvReqC}
|
||||
}
|
||||
|
||||
func (e *Watcher) Run(ctx context.Context) error {
|
||||
|
@ -138,7 +148,7 @@ func (e *Watcher) Run(ctx context.Context) error {
|
|||
}
|
||||
blocksBody, err := ioutil.ReadAll(resp.Body)
|
||||
if err != nil {
|
||||
logger.Error("query guardian set error", zap.Error(err))
|
||||
logger.Error("query latest block response read error", zap.Error(err))
|
||||
errC <- err
|
||||
resp.Body.Close()
|
||||
continue
|
||||
|
@ -156,6 +166,63 @@ func (e *Watcher) Run(ctx context.Context) error {
|
|||
}
|
||||
}()
|
||||
|
||||
go func() {
|
||||
for {
|
||||
select {
|
||||
case <-ctx.Done():
|
||||
return
|
||||
case r := <-e.obsvReqC:
|
||||
if vaa.ChainID(r.ChainId) != vaa.ChainIDTerra {
|
||||
panic("invalid chain ID")
|
||||
}
|
||||
|
||||
tx := hex.EncodeToString(r.TxHash)
|
||||
|
||||
logger.Info("received observation request for terra",
|
||||
zap.String("tx_hash", tx))
|
||||
|
||||
client := &http.Client{
|
||||
Timeout: time.Second * 5,
|
||||
}
|
||||
|
||||
// Query for tx by hash
|
||||
resp, err := client.Get(fmt.Sprintf("%s/cosmos/tx/v1beta1/txs/%s", e.urlLCD, tx))
|
||||
if err != nil {
|
||||
logger.Error("query tx response error", zap.Error(err))
|
||||
continue
|
||||
}
|
||||
txBody, err := ioutil.ReadAll(resp.Body)
|
||||
if err != nil {
|
||||
logger.Error("query tx response read error", zap.Error(err))
|
||||
resp.Body.Close()
|
||||
continue
|
||||
}
|
||||
resp.Body.Close()
|
||||
|
||||
txJSON := string(txBody)
|
||||
|
||||
txHashRaw := gjson.Get(txJSON, "tx_response.txhash")
|
||||
if !txHashRaw.Exists() {
|
||||
logger.Error("terra tx does not have tx hash", zap.String("payload", txJSON))
|
||||
continue
|
||||
}
|
||||
txHash := txHashRaw.String()
|
||||
|
||||
events := gjson.Get(txJSON, "tx_response.events")
|
||||
if !events.Exists() {
|
||||
logger.Error("terra tx has no events", zap.String("payload", txJSON))
|
||||
continue
|
||||
}
|
||||
|
||||
msgs := EventsToMessagePublications(e.contract, txHash, events.Array(), logger)
|
||||
for _, msg := range msgs {
|
||||
e.msgChan <- msg
|
||||
terraMessagesConfirmed.Inc()
|
||||
}
|
||||
}
|
||||
}
|
||||
}()
|
||||
|
||||
go func() {
|
||||
defer close(errC)
|
||||
|
||||
|
@ -185,7 +252,75 @@ func (e *Watcher) Run(ctx context.Context) error {
|
|||
continue
|
||||
}
|
||||
|
||||
for _, event := range events.Array() {
|
||||
msgs := EventsToMessagePublications(e.contract, txHash, events.Array(), logger)
|
||||
for _, msg := range msgs {
|
||||
e.msgChan <- msg
|
||||
terraMessagesConfirmed.Inc()
|
||||
}
|
||||
|
||||
client := &http.Client{
|
||||
Timeout: time.Second * 15,
|
||||
}
|
||||
|
||||
// Query and report guardian set status
|
||||
requestURL := fmt.Sprintf("%s/wasm/contracts/%s/store?query_msg={\"guardian_set_info\":{}}", e.urlLCD, e.contract)
|
||||
req, err := http.NewRequestWithContext(ctx, http.MethodGet, requestURL, nil)
|
||||
if err != nil {
|
||||
p2p.DefaultRegistry.AddErrorCount(vaa.ChainIDTerra, 1)
|
||||
terraConnectionErrors.WithLabelValues("guardian_set_req_error").Inc()
|
||||
logger.Error("query guardian set request error", zap.Error(err))
|
||||
errC <- err
|
||||
return
|
||||
}
|
||||
|
||||
msm := time.Now()
|
||||
resp, err := client.Do(req)
|
||||
if err != nil {
|
||||
p2p.DefaultRegistry.AddErrorCount(vaa.ChainIDTerra, 1)
|
||||
logger.Error("query guardian set response error", zap.Error(err))
|
||||
errC <- err
|
||||
return
|
||||
}
|
||||
|
||||
body, err := ioutil.ReadAll(resp.Body)
|
||||
queryLatency.WithLabelValues("guardian_set_info").Observe(time.Since(msm).Seconds())
|
||||
if err != nil {
|
||||
p2p.DefaultRegistry.AddErrorCount(vaa.ChainIDTerra, 1)
|
||||
logger.Error("query guardian set error", zap.Error(err))
|
||||
errC <- err
|
||||
resp.Body.Close()
|
||||
return
|
||||
}
|
||||
|
||||
json = string(body)
|
||||
guardianSetIndex := gjson.Get(json, "result.guardian_set_index")
|
||||
addresses := gjson.Get(json, "result.addresses.#.bytes")
|
||||
|
||||
logger.Debug("current guardian set on Terra",
|
||||
zap.Any("guardianSetIndex", guardianSetIndex),
|
||||
zap.Any("addresses", addresses))
|
||||
|
||||
resp.Body.Close()
|
||||
|
||||
// We do not send guardian changes to the processor - ETH guardians are the source of truth.
|
||||
}
|
||||
}()
|
||||
|
||||
select {
|
||||
case <-ctx.Done():
|
||||
err := c.WriteMessage(websocket.CloseMessage, websocket.FormatCloseMessage(websocket.CloseNormalClosure, ""))
|
||||
if err != nil {
|
||||
logger.Error("error on closing socket ", zap.Error(err))
|
||||
}
|
||||
return ctx.Err()
|
||||
case err := <-errC:
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
func EventsToMessagePublications(contract string, txHash string, events []gjson.Result, logger *zap.Logger) []*common.MessagePublication {
|
||||
msgs := make([]*common.MessagePublication, 0, len(events))
|
||||
for _, event := range events {
|
||||
if !event.IsObject() {
|
||||
logger.Warn("terra event is invalid", zap.String("tx_hash", txHash), zap.String("event", event.String()))
|
||||
continue
|
||||
|
@ -197,7 +332,7 @@ func (e *Watcher) Run(ctx context.Context) error {
|
|||
|
||||
attributes := gjson.Get(event.String(), "attributes")
|
||||
if !attributes.Exists() {
|
||||
logger.Warn("terra message event has no attributes", zap.String("payload", json), zap.String("event", event.String()))
|
||||
logger.Warn("terra message event has no attributes", zap.String("tx_hash", txHash), zap.String("event", event.String()))
|
||||
continue
|
||||
}
|
||||
mappedAttributes := map[string]string{}
|
||||
|
@ -207,12 +342,12 @@ func (e *Watcher) Run(ctx context.Context) error {
|
|||
continue
|
||||
}
|
||||
keyBase := gjson.Get(attribute.String(), "key")
|
||||
if !keyBase.Exists(){
|
||||
if !keyBase.Exists() {
|
||||
logger.Warn("terra event attribute does not have key", zap.String("tx_hash", txHash), zap.String("attribute", attribute.String()))
|
||||
continue
|
||||
}
|
||||
valueBase := gjson.Get(attribute.String(), "value")
|
||||
if !valueBase.Exists(){
|
||||
if !valueBase.Exists() {
|
||||
logger.Warn("terra event attribute does not have value", zap.String("tx_hash", txHash), zap.String("attribute", attribute.String()))
|
||||
continue
|
||||
}
|
||||
|
@ -242,7 +377,7 @@ func (e *Watcher) Run(ctx context.Context) error {
|
|||
continue
|
||||
}
|
||||
// This is not a wormhole message
|
||||
if contractAddress != e.contract {
|
||||
if contractAddress != contract {
|
||||
continue
|
||||
}
|
||||
|
||||
|
@ -327,68 +462,9 @@ func (e *Watcher) Run(ctx context.Context) error {
|
|||
Payload: payloadValue,
|
||||
ConsistencyLevel: 0, // Instant finality
|
||||
}
|
||||
e.msgChan <- messagePublication
|
||||
terraMessagesConfirmed.Inc()
|
||||
}
|
||||
|
||||
client := &http.Client{
|
||||
Timeout: time.Second * 15,
|
||||
}
|
||||
|
||||
// Query and report guardian set status
|
||||
requestURL := fmt.Sprintf("%s/wasm/contracts/%s/store?query_msg={\"guardian_set_info\":{}}", e.urlLCD, e.contract)
|
||||
req, err := http.NewRequestWithContext(ctx, http.MethodGet, requestURL, nil)
|
||||
if err != nil {
|
||||
p2p.DefaultRegistry.AddErrorCount(vaa.ChainIDTerra, 1)
|
||||
terraConnectionErrors.WithLabelValues("guardian_set_req_error").Inc()
|
||||
logger.Error("query guardian set request error", zap.Error(err))
|
||||
errC <- err
|
||||
return
|
||||
}
|
||||
|
||||
msm := time.Now()
|
||||
resp, err := client.Do(req)
|
||||
if err != nil {
|
||||
p2p.DefaultRegistry.AddErrorCount(vaa.ChainIDTerra, 1)
|
||||
logger.Error("query guardian set response error", zap.Error(err))
|
||||
errC <- err
|
||||
return
|
||||
}
|
||||
|
||||
body, err := ioutil.ReadAll(resp.Body)
|
||||
queryLatency.WithLabelValues("guardian_set_info").Observe(time.Since(msm).Seconds())
|
||||
if err != nil {
|
||||
p2p.DefaultRegistry.AddErrorCount(vaa.ChainIDTerra, 1)
|
||||
logger.Error("query guardian set error", zap.Error(err))
|
||||
errC <- err
|
||||
resp.Body.Close()
|
||||
return
|
||||
}
|
||||
|
||||
json = string(body)
|
||||
guardianSetIndex := gjson.Get(json, "result.guardian_set_index")
|
||||
addresses := gjson.Get(json, "result.addresses.#.bytes")
|
||||
|
||||
logger.Debug("current guardian set on Terra",
|
||||
zap.Any("guardianSetIndex", guardianSetIndex),
|
||||
zap.Any("addresses", addresses))
|
||||
|
||||
resp.Body.Close()
|
||||
|
||||
// We do not send guardian changes to the processor - ETH guardians are the source of truth.
|
||||
}
|
||||
}()
|
||||
|
||||
select {
|
||||
case <-ctx.Done():
|
||||
err := c.WriteMessage(websocket.CloseMessage, websocket.FormatCloseMessage(websocket.CloseNormalClosure, ""))
|
||||
if err != nil {
|
||||
logger.Error("error on closing socket ", zap.Error(err))
|
||||
}
|
||||
return ctx.Err()
|
||||
case err := <-errC:
|
||||
return err
|
||||
msgs = append(msgs, messagePublication)
|
||||
}
|
||||
return msgs
|
||||
}
|
||||
|
||||
// StringToAddress convert string into address
|
||||
|
|
Loading…
Reference in New Issue