Commit 74052928 authored by Heimdall's avatar Heimdall
Browse files

reschedule outbound tx if the previous outbound had been re-orged out of external chain

parent e3b2b73a
Pipeline #265099081 passed with stages
in 28 minutes and 49 seconds
......@@ -54,7 +54,7 @@ require (
golang.org/x/crypto v0.0.0-20210220033148-5ea612d1eb83 // indirect
golang.org/x/mod v0.4.0 // indirect
golang.org/x/tools v0.0.0-20210101214203-2dba1e4ea05c // indirect
google.golang.org/genproto v0.0.0-20210302174412-5ede27ff9881 // indirect
google.golang.org/genproto v0.0.0-20210303154014-9728d6b83eeb // indirect
gopkg.in/check.v1 v1.0.0-20200902074654-038fdea0a05b
gopkg.in/ini.v1 v1.52.0 // indirect
honnef.co/go/tools v0.0.1-2020.1.6 // indirect
......
......@@ -1429,8 +1429,8 @@ google.golang.org/genproto v0.0.0-20201022181438-0ff5f38871d5/go.mod h1:FWY/as6D
google.golang.org/genproto v0.0.0-20201111145450-ac7456db90a6/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
google.golang.org/genproto v0.0.0-20201119123407-9b1e624d6bc4/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
google.golang.org/genproto v0.0.0-20210114201628-6edceaf6022f/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
google.golang.org/genproto v0.0.0-20210302174412-5ede27ff9881 h1:SYuy3hIRsBIROE0aZwsJZOEJNC/n9/p0FmLEU9C31AE=
google.golang.org/genproto v0.0.0-20210302174412-5ede27ff9881/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
google.golang.org/genproto v0.0.0-20210303154014-9728d6b83eeb h1:hcskBH5qZCOa7WpTUFUFvoebnSFZBYpjykLtjIp9DVk=
google.golang.org/genproto v0.0.0-20210303154014-9728d6b83eeb/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
google.golang.org/grpc v1.17.0/go.mod h1:6QZJwpn2B+Zp71q/5VxRsJ6NXXVCE5NRUHRo+f3cWCs=
google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
google.golang.org/grpc v1.19.1/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
......
0.28.0
\ No newline at end of file
0.29.0
\ No newline at end of file
......@@ -10,6 +10,7 @@ import (
"gitlab.com/thorchain/thornode/common/cosmos"
"gitlab.com/thorchain/thornode/constants"
"gitlab.com/thorchain/thornode/x/thorchain/keeper"
memo "gitlab.com/thorchain/thornode/x/thorchain/memo"
)
// ErrataTxHandler is to handle ErrataTx message
......@@ -109,7 +110,11 @@ func (h ErrataTxHandler) handleV1(ctx cosmos.Context, msg MsgErrataTx, version s
}
if len(observedVoter.Txs) == 0 {
return nil, se.Wrap(errInternal, fmt.Sprintf("cannot find tx: %s", msg.TxID))
if version.GTE(semver.MustParse("0.29.0")) {
return h.processErrataOutboundTx(ctx, msg)
} else {
return nil, se.Wrap(errInternal, fmt.Sprintf("cannot find tx: %s", msg.TxID))
}
}
// set the observed Tx to reverted
observedVoter.SetReverted()
......@@ -191,3 +196,82 @@ func (h ErrataTxHandler) handleV1(ctx cosmos.Context, msg MsgErrataTx, version s
}
return &cosmos.Result{}, nil
}
// processErrataOutboundTx when the network detect an outbound tx which previously had been sent out to customer , however it get re-org , and it doesn't
// exist on the external chain anymore , then it will need to reschedule the tx
func (h ErrataTxHandler) processErrataOutboundTx(ctx cosmos.Context, msg MsgErrataTx) (*cosmos.Result, error) {
txOutVoter, err := h.keeper.GetObservedTxOutVoter(ctx, msg.GetTxID())
if err != nil {
return nil, fmt.Errorf("fail to get observed tx out voter for tx (%s) : %w", msg.GetTxID(), err)
}
if len(txOutVoter.Txs) == 0 {
return nil, fmt.Errorf("cannot find tx: %s", msg.TxID)
}
if txOutVoter.Tx.IsEmpty() {
return nil, fmt.Errorf("tx out voter is not finalised")
}
tx := txOutVoter.Tx.Tx
if !tx.Chain.Equals(msg.Chain) {
return &cosmos.Result{}, nil
}
// parse the outbound tx memo, so we can figure out which inbound tx triggered the outbound
m, err := memo.ParseMemo(tx.Memo)
if err != nil {
return nil, fmt.Errorf("fail to parse memo(%s): %w", tx.Memo, err)
}
if !m.IsOutbound() {
return nil, fmt.Errorf("%s is not outbound tx", m)
}
if m.IsInternal() {
ctx.Logger().Info("%s is internal tx , don't do anything", tx.Memo)
return &cosmos.Result{}, nil
}
vaultPubKey := txOutVoter.Tx.ObservedPubKey
if !vaultPubKey.IsEmpty() {
v, err := h.keeper.GetVault(ctx, vaultPubKey)
if err != nil {
return nil, fmt.Errorf("fail to get vault with pubkey %s: %w", vaultPubKey, err)
}
if v.IsAsgard() && (v.Status == RetiringVault || v.Status == ActiveVault) {
v.AddFunds(tx.Coins)
}
if v.IsYggdrasil() {
node, err := h.keeper.GetNodeAccountByPubKey(ctx, v.PubKey)
if err != nil {
return nil, fmt.Errorf("fail to get node account with pubkey: %s,err: %w", v.PubKey, err)
}
if !node.IsEmpty() && node.Status != NodeDisabled {
v.AddFunds(tx.Coins)
}
}
if err := h.keeper.SetVault(ctx, v); err != nil {
return nil, fmt.Errorf("fail to save vault: %w", err)
}
}
txInVoter, err := h.keeper.GetObservedTxInVoter(ctx, m.GetTxID())
if err != nil {
return nil, fmt.Errorf("fail to get tx in voter for tx (%s): %w", m.GetTxID(), err)
}
for _, item := range txInVoter.Actions {
if !item.OutHash.Equals(msg.GetTxID()) {
continue
}
newTxOutItem := TxOutItem{
Chain: item.Chain,
InHash: item.InHash,
ToAddress: item.ToAddress,
Coin: item.Coin,
Memo: item.Memo,
}
_, err := h.mgr.TxOutStore().TryAddTxOutItem(ctx, h.mgr, newTxOutItem)
if err != nil {
return nil, fmt.Errorf("fail to reschedule tx out item: %w", err)
}
break
}
txOutVoter.SetReverted()
h.keeper.SetObservedTxOutVoter(ctx, txOutVoter)
return &cosmos.Result{}, nil
}
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment