Skip to content

Commit 8fd9ddc

Browse files
committed
use latest darknode
1 parent 46d64a3 commit 8fd9ddc

35 files changed

+2480
-1037
lines changed

cacher/cacher.go

+2-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
package cacher
22

3-
import (
3+
/* import (
44
"database/sql"
55
"encoding/hex"
66
"encoding/json"
@@ -146,3 +146,4 @@ func (cacher *Cacher) dispatch(id [32]byte, msg http.RequestWithResponder) {
146146
msg.Responder <- response
147147
}()
148148
}
149+
*/

cacher/cacher_test.go

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
package cacher_test
22

3-
import (
3+
/* import (
44
"context"
55
"database/sql"
66
"encoding/json"
@@ -122,4 +122,4 @@ var _ = Describe("Cacher", func() {
122122
}
123123
})
124124
})
125-
})
125+
}) */

cmd/lightnode/lightnode.go

+39-44
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@ package main
22

33
import (
44
"context"
5-
"crypto/ecdsa"
65
"database/sql"
76
"encoding/hex"
87
"fmt"
@@ -19,8 +18,9 @@ import (
1918
"github.com/ethereum/go-ethereum/crypto"
2019
"github.com/evalphobia/logrus_sentry"
2120
"github.com/go-redis/redis/v7"
21+
"github.com/renproject/aw/wire"
2222
"github.com/renproject/darknode"
23-
"github.com/renproject/darknode/addr"
23+
"github.com/renproject/id"
2424
"github.com/renproject/lightnode"
2525
"github.com/sirupsen/logrus"
2626
)
@@ -31,21 +31,20 @@ func main() {
3131

3232
// Parse Lightnode options from environment variables.
3333
name := os.Getenv("HEROKU_APP_NAME")
34-
options := lightnode.Options{
35-
Network: parseNetwork(name),
36-
Key: parsePriKey(),
37-
DisPubkey: parsePubKey(),
38-
Port: os.Getenv("PORT"),
39-
ProtocolAddr: os.Getenv("PROTOCOL_ADDRESS"),
40-
Cap: parseInt("CAP"),
41-
MaxBatchSize: parseInt("MAX_BATCH_SIZE"),
42-
ServerTimeout: parseTime("SERVER_TIMEOUT"),
43-
ClientTimeout: parseTime("CLIENT_TIMEOUT"),
44-
TTL: parseTime("TTL"),
45-
UpdaterPollRate: parseTime("UPDATER_POLL_RATE"),
46-
ConfirmerPollRate: parseTime("CONFIRMER_POLL_RATE"),
47-
BootstrapAddrs: parseAddresses(),
48-
}
34+
options := lightnode.DefaultOptions().
35+
WithNetwork(parseNetwork(name)).
36+
WithKey(parsePrivKey()).
37+
WithDistPubKey(parsePubKey()).
38+
WithPort(os.Getenv("PORT")).
39+
WithProtocolAddr(os.Getenv("PROTOCOL_ADDRESS")).
40+
WithCap(parseInt("CAP")).
41+
WithMaxBatchSize(parseInt("MAX_BATCH_SIZE")).
42+
WithServerTimeout(parseTime("SERVER_TIMEOUT")).
43+
WithClientTimeout(parseTime("CLIENT_TIMEOUT")).
44+
WithTTL(parseTime("TTL")).
45+
WithUpdaterPollRate(parseTime("UPDATER_POLL_RATE")).
46+
WithConfirmerPollRate(parseTime("CONFIRMER_POLL_RATE")).
47+
WithBootstrapAddrs(parseAddresses())
4948

5049
// Initialise logger and attach Sentry hook.
5150
logger := initLogger(options.Network)
@@ -64,11 +63,11 @@ func main() {
6463

6564
// Run Lightnode.
6665
ctx := context.Background()
67-
node := lightnode.New(ctx, options, logger, sqlDB, client)
66+
node := lightnode.New(options, ctx, logger, sqlDB, client)
6867
node.Run(ctx)
6968
}
7069

71-
func initLogger(network darknode.Network) logrus.FieldLogger {
70+
func initLogger(network string) logrus.FieldLogger {
7271
logger := logrus.New()
7372
sentryURL := os.Getenv("SENTRY_URL")
7473
name := os.Getenv("HEROKU_APP_NAME")
@@ -105,19 +104,13 @@ func initRedis() *redis.Client {
105104
})
106105
}
107106

108-
func parseNetwork(appName string) darknode.Network {
107+
func parseNetwork(appName string) string {
109108
if strings.Contains(appName, "devnet") {
110109
return darknode.Devnet
111110
}
112111
if strings.Contains(appName, "testnet") {
113112
return darknode.Testnet
114113
}
115-
if strings.Contains(appName, "chaosnet") {
116-
return darknode.Chaosnet
117-
}
118-
if strings.Contains(appName, "localnet") {
119-
return darknode.Localnet
120-
}
121114
if strings.Contains(appName, "mainnet") {
122115
return darknode.Mainnet
123116
}
@@ -140,39 +133,41 @@ func parseTime(name string) time.Duration {
140133
return time.Duration(duration) * time.Second
141134
}
142135

143-
func parseAddresses() addr.MultiAddresses {
144-
addrs := strings.Split(os.Getenv("ADDRESSES"), ",")
145-
multis := make([]addr.MultiAddress, len(addrs))
146-
for i := range multis {
147-
multi, err := addr.NewMultiAddressFromString(addrs[i])
136+
func parseAddresses() []wire.Address {
137+
addrStrings := strings.Split(os.Getenv("ADDRESSES"), ",")
138+
addrs := make([]wire.Address, len(addrStrings))
139+
for i := range addrs {
140+
addr, err := wire.DecodeString(addrStrings[i])
148141
if err != nil {
149-
panic(fmt.Sprintf("invalid bootstrap address : fail to parse from string `%v`", addrs[i]))
142+
panic(fmt.Sprintf("invalid bootstrap address %v: %v", addrStrings[i], err))
150143
}
151-
multis[i] = multi
144+
addrs[i] = addr
152145
}
153-
return multis
146+
return addrs
154147
}
155148

156-
func parsePriKey() *ecdsa.PrivateKey {
157-
keyBytes, err := hex.DecodeString(os.Getenv("PRI_KEY"))
149+
func parsePrivKey() *id.PrivKey {
150+
privKeyString := os.Getenv("PRIV_KEY")
151+
keyBytes, err := hex.DecodeString(privKeyString)
158152
if err != nil {
159-
panic(fmt.Sprintf("invalid private key string from the env variable, err = %v", err))
153+
panic(fmt.Sprintf("invalid private key %v: %v", privKeyString, err))
160154
}
161155
key, err := crypto.ToECDSA(keyBytes)
162156
if err != nil {
163-
panic(fmt.Sprintf("invalid private key for lightnode account, err = %v", err))
157+
panic(fmt.Sprintf("invalid private key %v: %v", privKeyString, err))
164158
}
165-
return key
159+
return (*id.PrivKey)(key)
166160
}
167161

168-
func parsePubKey() *ecdsa.PublicKey {
169-
keyBytes, err := hex.DecodeString(os.Getenv("PUB_KEY"))
162+
func parsePubKey() *id.PubKey {
163+
pubKeyString := os.Getenv("PUB_KEY")
164+
keyBytes, err := hex.DecodeString(pubKeyString)
170165
if err != nil {
171-
panic(fmt.Sprintf("invalid public key string from the env variable, err = %v", err))
166+
panic(fmt.Sprintf("invalid distributed public key %v: %v", pubKeyString, err))
172167
}
173168
key, err := crypto.DecompressPubkey(keyBytes)
174169
if err != nil {
175-
panic(fmt.Sprintf("invalid distribute public key, err = %v", err))
170+
panic(fmt.Sprintf("invalid distributed public key %v: %v", pubKeyString, err))
176171
}
177-
return key
172+
return (*id.PubKey)(key)
178173
}

confirmer/confirmer.go

+53-54
Original file line numberDiff line numberDiff line change
@@ -9,46 +9,32 @@ import (
99
"strings"
1010
"time"
1111

12-
"github.com/renproject/darknode/abi"
1312
"github.com/renproject/darknode/jsonrpc"
13+
"github.com/renproject/darknode/tx"
14+
"github.com/renproject/darknode/txengine"
1415
"github.com/renproject/lightnode/db"
1516
"github.com/renproject/lightnode/http"
16-
"github.com/renproject/mercury/types/btctypes"
17+
"github.com/renproject/pack"
1718
"github.com/renproject/phi"
18-
"github.com/sirupsen/logrus"
1919
)
2020

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-
3321
// Confirmer handles requests that have been validated. It checks if requests
3422
// have reached sufficient confirmations and stores those that have not to be
3523
// checked later.
3624
type Confirmer struct {
37-
logger logrus.FieldLogger
3825
options Options
3926
dispatcher phi.Sender
4027
database db.DB
41-
bc ConnPool
28+
bindings txengine.Bindings
4229
}
4330

4431
// 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 {
4633
return Confirmer{
47-
logger: logger,
4834
options: options,
4935
dispatcher: dispatcher,
5036
database: db,
51-
bc: bc,
37+
bindings: bindings,
5238
}
5339
}
5440

@@ -94,37 +80,37 @@ func (confirmer *Confirmer) checkPendingTxs(parent context.Context) {
9480

9581
txs, err := confirmer.database.PendingTxs(24 * time.Hour)
9682
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)
9884
return
9985
}
10086

10187
phi.ParForAll(txs, func(i int) {
10288
tx := txs[i]
10389
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)
10692
} else {
107-
confirmed = confirmer.shiftOutTxConfirmed(ctx, tx)
93+
confirmed = confirmer.burnTxConfirmed(ctx, tx)
10894
}
10995

11096
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())
11298
confirmer.confirm(ctx, tx)
11399
}
114100
})
115101
}
116102

117103
// confirm sends the transaction to the dispatcher and marks it as confirmed if
118104
// 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)
121107
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)
123109
return
124110
}
125111
req := http.NewRequestWithResponder(ctx, request.ID, request.Method, request.Params, url.Values{})
126112
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")
128114
return
129115
}
130116

@@ -133,57 +119,70 @@ func (confirmer *Confirmer) confirm(ctx context.Context, tx abi.Tx) {
133119
case <-ctx.Done():
134120
return
135121
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)
140126
return
141127
}
142128

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)
145131
}
146132
}
147133
}()
148134
}
149135

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)
155150
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)
157152
return false
158153
}
159-
160-
return utxo.Confirmations() >= confirmer.options.MinConfirmations[tx.To]
154+
return true
161155
}
162156

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+
}
167165

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)
169167
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)
171169
return false
172170
}
173-
minCon := confirmer.options.MinConfirmations[tx.To]
174-
return confirmations >= minCon
171+
return true
175172
}
176173

177174
// prune removes any expired transactions from the database.
178175
func (confirmer *Confirmer) prune() {
179176
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)
181178
}
182179
}
183180

184181
// 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+
})
187186
if err != nil {
188187
return jsonrpc.Request{}, fmt.Errorf("failed to marshal tx: %v", err)
189188
}

confirmer/confirmer_test.go

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
package confirmer_test
22

3-
import (
3+
/* import (
44
"context"
55
"database/sql"
66
"time"
@@ -74,4 +74,4 @@ var _ = Describe("Confirmer", func() {
7474
}
7575
})
7676
})
77-
})
77+
}) */

0 commit comments

Comments
 (0)