-
Notifications
You must be signed in to change notification settings - Fork 0
/
processtx.go
111 lines (103 loc) · 3.02 KB
/
processtx.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
package block
import (
"fmt"
"github.com/weijun-sh/gethscan-server/log"
"github.com/weijun-sh/gethscan-server/tokens"
"github.com/weijun-sh/gethscan-server/tokens/btc/electrs"
"github.com/weijun-sh/gethscan-server/tokens/tools"
)
func (b *Bridge) processTransaction(txid string) {
var tx *electrs.ElectTx
var err error
for i := 0; i < 2; i++ {
tx, err = b.GetTransactionByHash(txid)
if err == nil {
break
}
}
if err != nil {
log.Debug("[processTransaction] "+b.ChainConfig.BlockChain+" Bridge::GetTransaction fail", "tx", txid, "err", err)
return
}
b.processTransactionImpl(tx)
}
func (b *Bridge) processTransactionImpl(tx *electrs.ElectTx) {
p2shBindAddrs, err := b.CheckSwapinTxType(tx)
if err != nil {
return
}
txid := *tx.Txid
if len(p2shBindAddrs) > 0 {
for _, p2shBindAddr := range p2shBindAddrs {
b.processP2shSwapin(txid, p2shBindAddr)
}
} else {
b.processSwapin(txid)
}
}
func (b *Bridge) processSwapin(txid string) {
if tools.IsSwapExist(txid, PairID, "", true) {
return
}
swapInfo, err := b.verifySwapinTx(PairID, txid, true)
tools.RegisterSwapin(txid, []*tokens.TxSwapInfo{swapInfo}, []error{err})
}
func (b *Bridge) processP2shSwapin(txid, bindAddress string) {
if tools.IsSwapExist(txid, PairID, bindAddress, true) {
return
}
swapInfo, err := b.verifyP2shSwapinTx(PairID, txid, bindAddress, true)
tools.RegisterP2shSwapin(txid, swapInfo, err)
}
func isP2pkhSwapinPrior(tx *electrs.ElectTx, depositAddress string) bool {
txFrom := getTxFrom(tx.Vin, depositAddress)
if txFrom == depositAddress {
return false
}
var memoScript string
for i := len(tx.Vout) - 1; i >= 0; i-- { // reverse iterate
output := tx.Vout[i]
if *output.ScriptpubkeyType == opReturnType {
memoScript = *output.ScriptpubkeyAsm
break
}
}
bindAddress, bindOk := GetBindAddressFromMemoScipt(memoScript)
return bindOk && tokens.DstBridge.IsValidAddress(bindAddress)
}
// CheckSwapinTxType check swapin type
func (b *Bridge) CheckSwapinTxType(tx *electrs.ElectTx) (p2shBindAddrs []string, err error) {
tokenCfg := b.GetTokenConfig(PairID)
if tokenCfg == nil {
return nil, fmt.Errorf("swap pair '%v' is not configed", PairID)
}
depositAddress := tokenCfg.DepositAddress
p2pkhSwapinPrior := isP2pkhSwapinPrior(tx, depositAddress)
p2shAddressMap := make(map[string]struct{})
for _, output := range tx.Vout {
if output.ScriptpubkeyAddress == nil {
continue
}
switch *output.ScriptpubkeyType {
case p2shType:
// use the first registered p2sh address
p2shAddress := *output.ScriptpubkeyAddress
if _, exist := p2shAddressMap[p2shAddress]; exist {
continue
}
p2shAddressMap[p2shAddress] = struct{}{}
p2shBindAddr := tools.GetP2shBindAddress(p2shAddress)
if p2shBindAddr != "" {
p2shBindAddrs = append(p2shBindAddrs, p2shBindAddr)
}
case p2pkhType:
if p2pkhSwapinPrior && *output.ScriptpubkeyAddress == depositAddress {
return nil, nil // use p2pkh if exist
}
}
}
if len(p2shBindAddrs) > 0 {
return p2shBindAddrs, nil
}
return nil, tokens.ErrTxWithWrongReceiver
}