Skip to content

Commit f95fc4a

Browse files
changes based on latest comments
1 parent dd56f89 commit f95fc4a

File tree

5 files changed

+91
-37
lines changed

5 files changed

+91
-37
lines changed

internal/serve/serve.go

+1
Original file line numberDiff line numberDiff line change
@@ -183,6 +183,7 @@ func initHandlerDeps(cfg Configs) (handlerDeps, error) {
183183

184184
// TSS setup
185185
tssTxService, err := tssservices.NewTransactionService(tssservices.TransactionServiceOptions{
186+
DB: dbConnectionPool,
186187
DistributionAccountSignatureClient: cfg.DistributionAccountSignatureClient,
187188
ChannelAccountSignatureClient: cfg.ChannelAccountSignatureClient,
188189
ChannelAccountStore: channelAccountStore,

internal/signing/env_signature_client.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ func (sc *envSignatureClient) NetworkPassphrase() string {
3636
return sc.networkPassphrase
3737
}
3838

39-
func (sc *envSignatureClient) GetAccountPublicKey(ctx context.Context, opts ...int) (string, error) {
39+
func (sc *envSignatureClient) GetAccountPublicKey(ctx context.Context, _ ...int) (string, error) {
4040
return sc.distributionAccountFull.Address(), nil
4141
}
4242

internal/signing/kms_signature_client.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@ func NewKMSSignatureClient(publicKey string, networkPassphrase string, keypairSt
5959
}, nil
6060
}
6161

62-
func (sc *kmsSignatureClient) GetAccountPublicKey(ctx context.Context, opts ...int) (string, error) {
62+
func (sc *kmsSignatureClient) GetAccountPublicKey(ctx context.Context, _ ...int) (string, error) {
6363
return sc.distributionAccountPublicKey, nil
6464
}
6565

internal/tss/services/transaction_service.go

+46-30
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import (
66

77
"github.com/stellar/go/txnbuild"
88

9+
"github.com/stellar/wallet-backend/internal/db"
910
"github.com/stellar/wallet-backend/internal/services"
1011
"github.com/stellar/wallet-backend/internal/signing"
1112
"github.com/stellar/wallet-backend/internal/signing/store"
@@ -18,6 +19,7 @@ type TransactionService interface {
1819
}
1920

2021
type transactionService struct {
22+
DB db.ConnectionPool
2123
DistributionAccountSignatureClient signing.SignatureClient
2224
ChannelAccountSignatureClient signing.SignatureClient
2325
ChannelAccountStore store.ChannelAccountStore
@@ -28,6 +30,7 @@ type transactionService struct {
2830
var _ TransactionService = (*transactionService)(nil)
2931

3032
type TransactionServiceOptions struct {
33+
DB db.ConnectionPool
3134
DistributionAccountSignatureClient signing.SignatureClient
3235
ChannelAccountSignatureClient signing.SignatureClient
3336
ChannelAccountStore store.ChannelAccountStore
@@ -36,6 +39,9 @@ type TransactionServiceOptions struct {
3639
}
3740

3841
func (o *TransactionServiceOptions) ValidateOptions() error {
42+
if o.DB == nil {
43+
return fmt.Errorf("DB cannot be nil")
44+
}
3945
if o.DistributionAccountSignatureClient == nil {
4046
return fmt.Errorf("distribution account signature client cannot be nil")
4147
}
@@ -64,6 +70,7 @@ func NewTransactionService(opts TransactionServiceOptions) (*transactionService,
6470
return nil, err
6571
}
6672
return &transactionService{
73+
DB: opts.DB,
6774
DistributionAccountSignatureClient: opts.DistributionAccountSignatureClient,
6875
ChannelAccountSignatureClient: opts.ChannelAccountSignatureClient,
6976
ChannelAccountStore: opts.ChannelAccountStore,
@@ -77,38 +84,47 @@ func (t *transactionService) NetworkPassphrase() string {
7784
}
7885

7986
func (t *transactionService) BuildAndSignTransactionWithChannelAccount(ctx context.Context, operations []txnbuild.Operation, timeoutInSecs int64) (*txnbuild.Transaction, error) {
80-
channelAccountPublicKey, err := t.ChannelAccountSignatureClient.GetAccountPublicKey(ctx, int(timeoutInSecs))
81-
if err != nil {
82-
return nil, fmt.Errorf("getting channel account public key: %w", err)
83-
}
84-
channelAccountSeq, err := t.RPCService.GetAccountLedgerSequence(channelAccountPublicKey)
85-
if err != nil {
86-
return nil, fmt.Errorf("getting ledger sequence for channel account public key: %s: %w", channelAccountPublicKey, err)
87-
}
88-
tx, err := txnbuild.NewTransaction(
89-
txnbuild.TransactionParams{
90-
SourceAccount: &txnbuild.SimpleAccount{
91-
AccountID: channelAccountPublicKey,
92-
Sequence: channelAccountSeq,
93-
},
94-
Operations: operations,
95-
BaseFee: int64(t.BaseFee),
96-
Preconditions: txnbuild.Preconditions{
97-
TimeBounds: txnbuild.NewTimeout(timeoutInSecs),
87+
var tx *txnbuild.Transaction
88+
var channelAccountPublicKey string
89+
err := db.RunInTransaction(ctx, t.DB, nil, func(dbTx db.Transaction) error {
90+
var err error
91+
channelAccountPublicKey, err = t.ChannelAccountSignatureClient.GetAccountPublicKey(ctx, int(timeoutInSecs))
92+
if err != nil {
93+
return fmt.Errorf("getting channel account public key: %w", err)
94+
}
95+
channelAccountSeq, err := t.RPCService.GetAccountLedgerSequence(channelAccountPublicKey)
96+
if err != nil {
97+
return fmt.Errorf("getting ledger sequence for channel account public key: %s: %w", channelAccountPublicKey, err)
98+
}
99+
tx, err = txnbuild.NewTransaction(
100+
txnbuild.TransactionParams{
101+
SourceAccount: &txnbuild.SimpleAccount{
102+
AccountID: channelAccountPublicKey,
103+
Sequence: channelAccountSeq,
104+
},
105+
Operations: operations,
106+
BaseFee: int64(t.BaseFee),
107+
Preconditions: txnbuild.Preconditions{
108+
TimeBounds: txnbuild.NewTimeout(timeoutInSecs),
109+
},
110+
IncrementSequenceNum: true,
98111
},
99-
IncrementSequenceNum: true,
100-
},
101-
)
102-
if err != nil {
103-
return nil, fmt.Errorf("building transaction: %w", err)
104-
}
105-
txHash, err := tx.HashHex(t.ChannelAccountSignatureClient.NetworkPassphrase())
112+
)
113+
if err != nil {
114+
return fmt.Errorf("building transaction: %w", err)
115+
}
116+
txHash, err := tx.HashHex(t.ChannelAccountSignatureClient.NetworkPassphrase())
117+
if err != nil {
118+
return fmt.Errorf("unable to hashhex transaction: %w", err)
119+
}
120+
err = t.ChannelAccountStore.AssignTxToChannelAccount(ctx, channelAccountPublicKey, txHash)
121+
if err != nil {
122+
return fmt.Errorf("assigning channel account to tx: %w", err)
123+
}
124+
return nil
125+
})
106126
if err != nil {
107-
return nil, fmt.Errorf("unable to hashhex transaction: %w", err)
108-
}
109-
err = t.ChannelAccountStore.AssignTxToChannelAccount(ctx, channelAccountPublicKey, txHash)
110-
if err != nil {
111-
return nil, fmt.Errorf("assigning channel account to tx: %w", err)
127+
return nil, err
112128
}
113129
tx, err = t.ChannelAccountSignatureClient.SignStellarTransaction(ctx, tx, channelAccountPublicKey)
114130
if err != nil {

internal/tss/services/transaction_service_test.go

+42-5
Original file line numberDiff line numberDiff line change
@@ -10,16 +10,37 @@ import (
1010
"github.com/stellar/go/txnbuild"
1111
"github.com/stretchr/testify/assert"
1212
"github.com/stretchr/testify/mock"
13+
"github.com/stretchr/testify/require"
1314

15+
"github.com/stellar/wallet-backend/internal/db"
16+
"github.com/stellar/wallet-backend/internal/db/dbtest"
1417
"github.com/stellar/wallet-backend/internal/services"
1518
"github.com/stellar/wallet-backend/internal/signing"
1619
"github.com/stellar/wallet-backend/internal/signing/store"
1720
"github.com/stellar/wallet-backend/internal/tss/utils"
1821
)
1922

2023
func TestValidateOptions(t *testing.T) {
24+
dbt := dbtest.Open(t)
25+
defer dbt.Close()
26+
dbConnectionPool, err := db.OpenDBConnectionPool(dbt.DSN)
27+
require.NoError(t, err)
28+
defer dbConnectionPool.Close()
29+
t.Run("return_error_when_db_nil", func(t *testing.T) {
30+
opts := TransactionServiceOptions{
31+
DistributionAccountSignatureClient: nil,
32+
ChannelAccountSignatureClient: &signing.SignatureClientMock{},
33+
ChannelAccountStore: &store.ChannelAccountStoreMock{},
34+
RPCService: &services.RPCServiceMock{},
35+
BaseFee: 114,
36+
}
37+
err := opts.ValidateOptions()
38+
assert.Equal(t, "DB cannot be nil", err.Error())
39+
40+
})
2141
t.Run("return_error_when_distribution_signature_client_nil", func(t *testing.T) {
2242
opts := TransactionServiceOptions{
43+
DB: dbConnectionPool,
2344
DistributionAccountSignatureClient: nil,
2445
ChannelAccountSignatureClient: &signing.SignatureClientMock{},
2546
ChannelAccountStore: &store.ChannelAccountStoreMock{},
@@ -33,6 +54,7 @@ func TestValidateOptions(t *testing.T) {
3354

3455
t.Run("return_error_when_channel_signature_client_nil", func(t *testing.T) {
3556
opts := TransactionServiceOptions{
57+
DB: dbConnectionPool,
3658
DistributionAccountSignatureClient: &signing.SignatureClientMock{},
3759
ChannelAccountSignatureClient: nil,
3860
ChannelAccountStore: &store.ChannelAccountStoreMock{},
@@ -45,6 +67,7 @@ func TestValidateOptions(t *testing.T) {
4567

4668
t.Run("return_error_when_channel_account_store_nil", func(t *testing.T) {
4769
opts := TransactionServiceOptions{
70+
DB: dbConnectionPool,
4871
DistributionAccountSignatureClient: &signing.SignatureClientMock{},
4972
ChannelAccountSignatureClient: &signing.SignatureClientMock{},
5073
ChannelAccountStore: nil,
@@ -57,6 +80,7 @@ func TestValidateOptions(t *testing.T) {
5780

5881
t.Run("return_error_when_rpc_client_nil", func(t *testing.T) {
5982
opts := TransactionServiceOptions{
83+
DB: dbConnectionPool,
6084
DistributionAccountSignatureClient: &signing.SignatureClientMock{},
6185
ChannelAccountSignatureClient: &signing.SignatureClientMock{},
6286
ChannelAccountStore: &store.ChannelAccountStoreMock{},
@@ -69,6 +93,7 @@ func TestValidateOptions(t *testing.T) {
6993

7094
t.Run("return_error_when_base_fee_too_low", func(t *testing.T) {
7195
opts := TransactionServiceOptions{
96+
DB: dbConnectionPool,
7297
DistributionAccountSignatureClient: &signing.SignatureClientMock{},
7398
ChannelAccountSignatureClient: &signing.SignatureClientMock{},
7499
ChannelAccountStore: &store.ChannelAccountStoreMock{},
@@ -81,18 +106,24 @@ func TestValidateOptions(t *testing.T) {
81106
}
82107

83108
func TestBuildAndSignTransactionWithChannelAccount(t *testing.T) {
109+
dbt := dbtest.Open(t)
110+
defer dbt.Close()
111+
dbConnectionPool, err := db.OpenDBConnectionPool(dbt.DSN)
112+
require.NoError(t, err)
113+
defer dbConnectionPool.Close()
84114
distributionAccountSignatureClient := signing.SignatureClientMock{}
85115
channelAccountSignatureClient := signing.SignatureClientMock{}
86116
channelAccountStore := store.ChannelAccountStoreMock{}
87117
mockRPCService := &services.RPCServiceMock{}
88118
txService, _ := NewTransactionService(TransactionServiceOptions{
119+
DB: dbConnectionPool,
89120
DistributionAccountSignatureClient: &distributionAccountSignatureClient,
90121
ChannelAccountSignatureClient: &channelAccountSignatureClient,
91122
ChannelAccountStore: &channelAccountStore,
92123
RPCService: mockRPCService,
93124
BaseFee: 114,
94125
})
95-
126+
atomicTxErrorPrefix := "running atomic function in RunInTransactionWithResult: "
96127
t.Run("channel_account_signature_client_get_account_public_key_err", func(t *testing.T) {
97128
channelAccountSignatureClient.
98129
On("GetAccountPublicKey", context.Background()).
@@ -103,7 +134,7 @@ func TestBuildAndSignTransactionWithChannelAccount(t *testing.T) {
103134

104135
channelAccountSignatureClient.AssertExpectations(t)
105136
assert.Empty(t, tx)
106-
assert.Equal(t, "getting channel account public key: channel accounts unavailable", err.Error())
137+
assert.Equal(t, atomicTxErrorPrefix+"getting channel account public key: channel accounts unavailable", err.Error())
107138
})
108139

109140
t.Run("rpc_client_get_account_seq_err", func(t *testing.T) {
@@ -124,7 +155,7 @@ func TestBuildAndSignTransactionWithChannelAccount(t *testing.T) {
124155
channelAccountSignatureClient.AssertExpectations(t)
125156
assert.Empty(t, tx)
126157
expectedErr := fmt.Errorf("getting ledger sequence for channel account public key: %s: rpc service down", channelAccount.Address())
127-
assert.Equal(t, expectedErr.Error(), err.Error())
158+
assert.Equal(t, atomicTxErrorPrefix+expectedErr.Error(), err.Error())
128159
})
129160

130161
t.Run("build_tx_fails", func(t *testing.T) {
@@ -144,7 +175,7 @@ func TestBuildAndSignTransactionWithChannelAccount(t *testing.T) {
144175

145176
channelAccountSignatureClient.AssertExpectations(t)
146177
assert.Empty(t, tx)
147-
assert.Equal(t, "building transaction: transaction has no operations", err.Error())
178+
assert.Equal(t, atomicTxErrorPrefix+"building transaction: transaction has no operations", err.Error())
148179

149180
})
150181

@@ -180,7 +211,7 @@ func TestBuildAndSignTransactionWithChannelAccount(t *testing.T) {
180211
channelAccountSignatureClient.AssertExpectations(t)
181212
channelAccountStore.AssertExpectations(t)
182213
assert.Empty(t, tx)
183-
assert.Equal(t, "assigning channel account to tx: unable to assign channel account to tx", err.Error())
214+
assert.Equal(t, atomicTxErrorPrefix+"assigning channel account to tx: unable to assign channel account to tx", err.Error())
184215
})
185216

186217
t.Run("sign_stellar_transaction_w_channel_account_err", func(t *testing.T) {
@@ -261,11 +292,17 @@ func TestBuildAndSignTransactionWithChannelAccount(t *testing.T) {
261292
}
262293

263294
func TestBuildFeeBumpTransaction(t *testing.T) {
295+
dbt := dbtest.Open(t)
296+
defer dbt.Close()
297+
dbConnectionPool, err := db.OpenDBConnectionPool(dbt.DSN)
298+
require.NoError(t, err)
299+
defer dbConnectionPool.Close()
264300
distributionAccountSignatureClient := signing.SignatureClientMock{}
265301
channelAccountSignatureClient := signing.SignatureClientMock{}
266302
channelAccountStore := store.ChannelAccountStoreMock{}
267303
mockRPCService := &services.RPCServiceMock{}
268304
txService, _ := NewTransactionService(TransactionServiceOptions{
305+
DB: dbConnectionPool,
269306
DistributionAccountSignatureClient: &distributionAccountSignatureClient,
270307
ChannelAccountSignatureClient: &channelAccountSignatureClient,
271308
ChannelAccountStore: &channelAccountStore,

0 commit comments

Comments
 (0)