@@ -9,46 +9,32 @@ import (
9
9
"strings"
10
10
"time"
11
11
12
- "github.com/renproject/darknode/abi"
13
12
"github.com/renproject/darknode/jsonrpc"
13
+ "github.com/renproject/darknode/tx"
14
+ "github.com/renproject/darknode/txengine"
14
15
"github.com/renproject/lightnode/db"
15
16
"github.com/renproject/lightnode/http"
16
- "github.com/renproject/mercury/types/btctypes "
17
+ "github.com/renproject/pack "
17
18
"github.com/renproject/phi"
18
- "github.com/sirupsen/logrus"
19
19
)
20
20
21
- type ConnPool interface {
22
- Utxo (ctx context.Context , addr abi.Address , hash abi.B32 , vout abi.U32 ) (btctypes.UTXO , error )
23
- EventConfirmations (ctx context.Context , addr abi.Address , ref uint64 ) (uint64 , error )
24
- }
25
-
26
- // Options for initialising a confirmer.
27
- type Options struct {
28
- MinConfirmations map [abi.Address ]uint64
29
- PollInterval time.Duration
30
- Expiry time.Duration
31
- }
32
-
33
21
// Confirmer handles requests that have been validated. It checks if requests
34
22
// have reached sufficient confirmations and stores those that have not to be
35
23
// checked later.
36
24
type Confirmer struct {
37
- logger logrus.FieldLogger
38
25
options Options
39
26
dispatcher phi.Sender
40
27
database db.DB
41
- bc ConnPool
28
+ bindings txengine. Bindings
42
29
}
43
30
44
31
// New returns a new Confirmer.
45
- func New (logger logrus. FieldLogger , options Options , dispatcher phi.Sender , db db.DB , bc ConnPool ) Confirmer {
32
+ func New (options Options , dispatcher phi.Sender , db db.DB , bindings txengine. Bindings ) Confirmer {
46
33
return Confirmer {
47
- logger : logger ,
48
34
options : options ,
49
35
dispatcher : dispatcher ,
50
36
database : db ,
51
- bc : bc ,
37
+ bindings : bindings ,
52
38
}
53
39
}
54
40
@@ -94,37 +80,37 @@ func (confirmer *Confirmer) checkPendingTxs(parent context.Context) {
94
80
95
81
txs , err := confirmer .database .PendingTxs (24 * time .Hour )
96
82
if err != nil {
97
- confirmer .logger .Errorf ("[confirmer] failed to read pending txs from database: %v" , err )
83
+ confirmer .options . Logger .Errorf ("[confirmer] failed to read pending txs from database: %v" , err )
98
84
return
99
85
}
100
86
101
87
phi .ParForAll (txs , func (i int ) {
102
88
tx := txs [i ]
103
89
var confirmed bool
104
- if abi . IsShiftIn ( tx .To ) {
105
- confirmed = confirmer .shiftInTxConfirmed (ctx , tx )
90
+ if tx .Selector . IsLockAndMint ( ) {
91
+ confirmed = confirmer .lockTxConfirmed (ctx , tx )
106
92
} else {
107
- confirmed = confirmer .shiftOutTxConfirmed (ctx , tx )
93
+ confirmed = confirmer .burnTxConfirmed (ctx , tx )
108
94
}
109
95
110
96
if confirmed {
111
- confirmer .logger .Infof ("tx=%v has reached sufficient confirmations" , tx .Hash .String ())
97
+ confirmer .options . Logger .Infof ("tx=%v has reached sufficient confirmations" , tx .Hash .String ())
112
98
confirmer .confirm (ctx , tx )
113
99
}
114
100
})
115
101
}
116
102
117
103
// confirm sends the transaction to the dispatcher and marks it as confirmed if
118
104
// it receives a non-error response from the Darknodes.
119
- func (confirmer * Confirmer ) confirm (ctx context.Context , tx abi .Tx ) {
120
- request , err := submitTxRequest (tx )
105
+ func (confirmer * Confirmer ) confirm (ctx context.Context , transaction tx .Tx ) {
106
+ request , err := submitTxRequest (transaction )
121
107
if err != nil {
122
- confirmer .logger .Errorf ("[confirmer] cannot construct json request for transaction: %v" , err )
108
+ confirmer .options . Logger .Errorf ("[confirmer] cannot construct json request for transaction: %v" , err )
123
109
return
124
110
}
125
111
req := http .NewRequestWithResponder (ctx , request .ID , request .Method , request .Params , url.Values {})
126
112
if ok := confirmer .dispatcher .Send (req ); ! ok {
127
- confirmer .logger . Errorf ("[confirmer] cannot send message to dispatcher, too much back pressure" )
113
+ confirmer .options . Logger . Errorf ("[confirmer] cannot send message to dispatcher: too much back pressure" )
128
114
return
129
115
}
130
116
@@ -133,57 +119,70 @@ func (confirmer *Confirmer) confirm(ctx context.Context, tx abi.Tx) {
133
119
case <- ctx .Done ():
134
120
return
135
121
case response := <- req .Responder :
136
- if response .Error == nil {
137
- confirmer .logger . Infof ("✅ successfully submit tx = %v to darknodes" , tx .Hash .String ())
138
- } else if response . Error != nil && ! strings . Contains ( response . Error . Message , "current status = done" ) {
139
- confirmer .logger . Errorf ("[confirmer] getting error back when submitting tx = %v: [%v] %v" , tx .Hash .String (), response .Error .Code , response .Error .Message )
122
+ if response .Error == nil || strings . Contains ( response . Error . Message , "current status = done" ) {
123
+ confirmer .options . Logger . Infof ("✅ successfully submitted tx= %v to darknodes" , transaction .Hash .String ())
124
+ } else {
125
+ confirmer .options . Logger . Errorf ("[confirmer] getting error back when submitting tx= %v: [%v] %v" , transaction .Hash .String (), response .Error .Code , response .Error .Message )
140
126
return
141
127
}
142
128
143
- if err := confirmer .database .UpdateStatus (tx .Hash , db .TxStatusConfirmed ); err != nil {
144
- confirmer .logger . Errorf ("[confirmer] cannot confirm tx in the database : %v" , err )
129
+ if err := confirmer .database .UpdateStatus (transaction .Hash , db .TxStatusConfirmed ); err != nil {
130
+ confirmer .options . Logger . Errorf ("[confirmer] cannot update transaction status : %v" , err )
145
131
}
146
132
}
147
133
}()
148
134
}
149
135
150
- // shiftInTxConfirmed checks if a given shift in transaction has received
151
- // sufficient confirmations.
152
- func (confirmer * Confirmer ) shiftInTxConfirmed (ctx context.Context , tx abi.Tx ) bool {
153
- utxoVal := tx .In .Get ("utxo" ).Value .(abi.ExtBtcCompatUTXO )
154
- utxo , err := confirmer .bc .Utxo (ctx , tx .To , utxoVal .TxHash , utxoVal .VOut )
136
+ // lockTxConfirmed checks if a given lock transaction has received sufficient
137
+ // confirmations.
138
+ func (confirmer * Confirmer ) lockTxConfirmed (ctx context.Context , transaction tx.Tx ) bool {
139
+ lockChain , ok := transaction .Selector .LockChain ()
140
+ if ! ok {
141
+ confirmer .options .Logger .Errorf ("[confirmer] cannot get lock chain for tx=%v (%v)" , transaction .Hash .String (), transaction .Selector .String ())
142
+ return false
143
+ }
144
+ input := txengine.UTXOLockAndMintInput {}
145
+ if err := pack .Decode (& input , transaction .Input ); err != nil {
146
+ confirmer .options .Logger .Errorf ("[confirmer] failed to decode input for tx=%v: %v" , transaction .Hash .String (), err )
147
+ return false
148
+ }
149
+ utxo , err := confirmer .bindings .UTXOLockInfo (ctx , lockChain , transaction .Selector .Asset (), input .Output .Outpoint )
155
150
if err != nil {
156
- confirmer .logger . Errorf ("[confirmer] cannot get confirmation for tx=%v (%v): %v" , utxoVal . TxHash . String (), tx . To , err )
151
+ confirmer .options . Logger . Errorf ("[confirmer] cannot get output for btc tx=%v (%v): %v" , utxo . Outpoint . Hash . String (), transaction . Selector . String () , err )
157
152
return false
158
153
}
159
-
160
- return utxo .Confirmations () >= confirmer .options .MinConfirmations [tx .To ]
154
+ return true
161
155
}
162
156
163
- // shiftOutTxConfirmed checks if a given shift out transaction has received
164
- // sufficient confirmations.
165
- func (confirmer * Confirmer ) shiftOutTxConfirmed (ctx context.Context , tx abi.Tx ) bool {
166
- ref := tx .In .Get ("ref" ).Value .(abi.U64 )
157
+ // burnTxConfirmed checks if a given burn transaction has received sufficient
158
+ // confirmations.
159
+ func (confirmer * Confirmer ) burnTxConfirmed (ctx context.Context , transaction tx.Tx ) bool {
160
+ nonce , ok := transaction .Input .Get ("nonce" ).(pack.Bytes32 )
161
+ if ! ok {
162
+ confirmer .options .Logger .Errorf ("[confirmer] failed to get nonce for tx=%v" , transaction .Hash .String ())
163
+ return false
164
+ }
167
165
168
- confirmations , err := confirmer .bc . EventConfirmations (ctx , tx . To , ref . Int . Uint64 () )
166
+ _ , _ , _ , err := confirmer .bindings . AccountBurnInfo (ctx , transaction . Selector . Asset (). OriginChain (), transaction . Selector . Asset (), nonce )
169
167
if err != nil {
170
- confirmer .logger . Errorf ("[confirmer] cannot get confirmation for ethereum event (%v): %v" , tx . To , err )
168
+ confirmer .options . Logger . Errorf ("[confirmer] cannot get burn info for tx=%v (%v): %v" , transaction . Hash . String (), transaction . Selector . String () , err )
171
169
return false
172
170
}
173
- minCon := confirmer .options .MinConfirmations [tx .To ]
174
- return confirmations >= minCon
171
+ return true
175
172
}
176
173
177
174
// prune removes any expired transactions from the database.
178
175
func (confirmer * Confirmer ) prune () {
179
176
if err := confirmer .database .Prune (confirmer .options .Expiry ); err != nil {
180
- confirmer .logger .Errorf ("[confirmer] cannot prune database: %v" , err )
177
+ confirmer .options . Logger .Errorf ("[confirmer] cannot prune database: %v" , err )
181
178
}
182
179
}
183
180
184
181
// submitTxRequest converts a transaction to a `jsonrpc.Request`.
185
- func submitTxRequest (tx abi.Tx ) (jsonrpc.Request , error ) {
186
- data , err := json .Marshal (jsonrpc.ParamsSubmitTx {Tx : tx })
182
+ func submitTxRequest (transaction tx.Tx ) (jsonrpc.Request , error ) {
183
+ data , err := json .Marshal (jsonrpc.ParamsSubmitTx {
184
+ Tx : transaction ,
185
+ })
187
186
if err != nil {
188
187
return jsonrpc.Request {}, fmt .Errorf ("failed to marshal tx: %v" , err )
189
188
}
0 commit comments