Skip to content

Commit 841a178

Browse files
committed
Fix intent cache
1 parent 92fcdcb commit 841a178

File tree

3 files changed

+29
-46
lines changed

3 files changed

+29
-46
lines changed

server/internal/infrastructure/live-store/inmemory/intents.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ func (m *txRequestStore) Push(request domain.TxRequest, boardingInputs []ports.B
5353
for _, pay := range m.requests {
5454
for _, pInput := range pay.Inputs {
5555
if input.Txid == pInput.Txid && input.VOut == pInput.VOut {
56-
return fmt.Errorf("duplicated input, %s:%d already used by tx request %s", input.Txid, input.VOut, pay.Id)
56+
return fmt.Errorf("duplicated input, %s already registered by another request", input.String())
5757
}
5858
}
5959
}
@@ -63,7 +63,7 @@ func (m *txRequestStore) Push(request domain.TxRequest, boardingInputs []ports.B
6363
for _, request := range m.requests {
6464
for _, pBoardingInput := range request.BoardingInputs {
6565
if input.Txid == pBoardingInput.Txid && input.VOut == pBoardingInput.VOut {
66-
return fmt.Errorf("duplicated boarding input, %s:%d already used by tx request %s", input.Txid, input.VOut, request.Id)
66+
return fmt.Errorf("duplicated input, %s already registered by another request", input.String())
6767
}
6868
}
6969
}

server/internal/infrastructure/live-store/live_store_test.go

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ var (
3333

3434
txReqFixture1 = `{"boardingInputs":[{"Txid":"1e1448b9f2c44e4bc861db45864097d94fa7519dab9cba12c886a0c244932145","VOut":1,"Tapscripts":["039d0440b27520fa8c9a09b46c5ee858e239684b0bb7229c7d38f1fc05b3e3ef04ddff6d4e5a4eac","20fa8c9a09b46c5ee858e239684b0bb7229c7d38f1fc05b3e3ef04ddff6d4e5a4ead203696e749f125347d82f2c0a173a60a6efa117daec654caa4f78c1794c8fd0f23ac"],"Amount":100000000}],"cosignerPubkeys":["039f2214798b94cd517ccd561e739ebb73cecacdc41b387beb460dda097c2b7c67"],"request":{"Id":"0222bfa8-c753-4b41-a5f9-d4e12d726413","Inputs":[{"Txid":"24de502601c21cf7b227c0667ffe1175841cdd4f6e5b20d3063387333d0b10da","VOut":0,"CommitmentTxid":"0000000000000000000000000000000000000000000000000000000000000000"}],"Receivers":[{"Amount":100000000,"OnchainAddress":"","PubKey":"7594c9acd996ccf667431769bb4b238b29a9ed32b73f39185c121cf770aa0a63"}]}}`
3535
txReqFixture2 = `{"boardingInputs":[{"Txid":"14de502601c21cf7b227c0667ffe1175841cdd4f6e5b20d3063387333d0b10db","VOut":1,"Tapscripts":["039d0440b275202f2ae2cdad60893ec73c5c44a9b23a4addfe859baaf1754fe193da27f31ea754ac","202f2ae2cdad60893ec73c5c44a9b23a4addfe859baaf1754fe193da27f31ea754ad203696e749f125347d82f2c0a173a60a6efa117daec654caa4f78c1794c8fd0f23ac"],"Amount":100000000}],"cosignerPubkeys":["021f5b9ff8f25ff7b8984f444abb75621267251cbba76f32d12bf6b4da3b3a7096"],"request":{"Id":"2a4d69f3-ce1b-40b3-a48d-fb61ec21b15f","Inputs":[],"Receivers":[{"Amount":100000000,"OnchainAddress":"","PubKey":"7086d72a8ddacc9e6e0451d92133ef583d6748a4726b632a94f26df8c802ac24"}]}}`
36+
txReqFixture3 = `{"boardingInputs":[{"Txid":"1e1448b9f2c44e4bc861db45864097d94fa7519dab9cba12c886a0c244932145","VOut":1,"Tapscripts":["039d0440b27520fa8c9a09b46c5ee858e239684b0bb7229c7d38f1fc05b3e3ef04ddff6d4e5a4eac","20fa8c9a09b46c5ee858e239684b0bb7229c7d38f1fc05b3e3ef04ddff6d4e5a4ead203696e749f125347d82f2c0a173a60a6efa117daec654caa4f78c1794c8fd0f23ac"],"Amount":100000000}],"cosignerPubkeys":["039f2214798b94cd517ccd561e739ebb73cecacdc41b387beb460dda097c2b7c67"],"request":{"Id":"aaaaaaaa-c753-4b41-a5f9-d4e12d726413","Inputs":[{"Txid":"24de502601c21cf7b227c0667ffe1175841cdd4f6e5b20d3063387333d0b10da","VOut":0,"CommitmentTxid":"0000000000000000000000000000000000000000000000000000000000000000"}],"Receivers":[{"Amount":100000000,"OnchainAddress":"","PubKey":"7594c9acd996ccf667431769bb4b238b29a9ed32b73f39185c121cf770aa0a63"}]}}`
3637

3738
offchainTxJSON = `{"Stage":{"Code":2,"Ended":false,"Failed":false},"StartingTimestamp":1749818677,"EndingTimestamp":0,"VirtualTxid":"79e74bf97b34450d69780778522087504e5340dd71c7454b017c01e3d3bfb8ab","VirtualTx":"cHNidP8BAJYDAAAAAeB4gUdsoDHu7o2F4IkLICEbEt0y9MejPi5mWzdZtxBBAAAAAAD/////A4gTAAAAAAAAIlEgcIbXKo3azJ5uBFHZITPvWD1nSKRya2MqlPJt+MgCrCR4zfUFAAAAACJRIHWUyazZlsz2Z0MXabtLI4spqe0ytz85GFwSHPdwqgpjAAAAAAAAAAAEUQJOcwAAAAAAAQErAOH1BQAAAAAiUSDTwlo9WBKfqLWlkkznHmITfQzQEU37+YWWyqn5B2dyGEEU+oyaCbRsXuhY4jloSwu3Ipx9OPH8BbPj7wTd/21OWk4MjR6TYePp/0T4p433ieP80aFTXXPgoCOHPjELdrL+AUDpuqwgR4YEuiemShPyiNdDm0AX1aj0sm1E5JUWApXGIahSpPpWhImz2GlO+PMJHdVNXEKXoDePj91v6H6PK1a0QRQ2ludJ8SU0fYLywKFzpgpu+hF9rsZUyqT3jBeUyP0PIwyNHpNh4+n/RPinjfeJ4/zRoVNdc+CgI4c+MQt2sv4BQInUzArzkE6X+bP/eCF7F1PzaedGuM4wtX5roc9fOZ1Ja0XTErh5GUWMdZUGaqIDBlbggnPZjidgCFpV1DlEry5CFcFQkpt0waBJVLeLS2A16XpeB4paDyjsltVHv+6azoA6wOlm8s7rZPsauycdJTy6UH8o1nvcz68gOYxt8V80njVkRSD6jJoJtGxe6FjiOWhLC7cinH048fwFs+PvBN3/bU5aTq0gNpbnSfElNH2C8sChc6YKbvoRfa7GVMqk94wXlMj9DyOswAd0YXB0cmVlcwIBwCgDAgBAsnUgNpbnSfElNH2C8sChc6YKbvoRfa7GVMqk94wXlMj9DyOsAcBEIPqMmgm0bF7oWOI5aEsLtyKcfTjx/AWz4+8E3f9tTlpOrSA2ludJ8SU0fYLywKFzpgpu+hF9rsZUyqT3jBeUyP0PI6wAAAAA","CheckpointTxs":{"4110b759375b662e3ea3c7f432dd121b21200b89e0858deeee31a06c478178e0":"cHNidP8BAGsDAAAAARrFJ/P3vwEZY75OHSqgWMz3RaeIrDt7pxWqEAXZwfz+AAAAAAD/////AgDh9QUAAAAAIlEg08JaPVgSn6i1pZJM5x5iE30M0BFN+/mFlsqp+QdnchgAAAAAAAAAAARRAk5zAAAAAAABASsA4fUFAAAAACJRIHWUyazZlsz2Z0MXabtLI4spqe0ytz85GFwSHPdwqgpjQRQ2ludJ8SU0fYLywKFzpgpu+hF9rsZUyqT3jBeUyP0PIwyNHpNh4+n/RPinjfeJ4/zRoVNdc+CgI4c+MQt2sv4BQCgwEdt3LF/ub7J1hnF3+kbMvbo0Wqt3VpGDsto8wiqy6KL6zHMxKYEZAn1z3SLCo7wKZFsWk1gdx65rINE5JM5CFcBQkpt0waBJVLeLS2A16XpeB4paDyjsltVHv+6azoA6wHYMhmDVZUYnxrCdnty+DMhKJTmw60ZDqTPzCAavjN5ERSD6jJoJtGxe6FjiOWhLC7cinH048fwFs+PvBN3/bU5aTq0gNpbnSfElNH2C8sChc6YKbvoRfa7GVMqk94wXlMj9DyOswAd0YXB0cmVlcwIBwCgDAgBAsnUg+oyaCbRsXuhY4jloSwu3Ipx9OPH8BbPj7wTd/21OWk6sAcBEIPqMmgm0bF7oWOI5aEsLtyKcfTjx/AWz4+8E3f9tTlpOrSA2ludJ8SU0fYLywKFzpgpu+hF9rsZUyqT3jBeUyP0PI6wAAAA="},"CommitmentTxids":{"4110b759375b662e3ea3c7f432dd121b21200b89e0858deeee31a06c478178e0":"2c6bffc1ce2da7e40f37043b7940b548b9b93f474e17c7fd84c8090c054afc96"},"RootCommitmentTxId":"2c6bffc1ce2da7e40f37043b7940b548b9b93f474e17c7fd84c8090c054afc96","ExpiryTimestamp":199,"FailReason":"","Version":0}`
3839

@@ -85,10 +86,16 @@ func runLiveStoreTests(t *testing.T, store ports.LiveStore) {
8586
require.NoError(t, err)
8687
req2, err := parseTxRequestsFixtures(txReqFixture2)
8788
require.NoError(t, err)
89+
req3, err := parseTxRequestsFixtures(txReqFixture3)
90+
require.NoError(t, err)
8891

8992
// Push
9093
err = store.TxRequests().Push(req1.Request, req1.BoardingInputs, req1.CosignersPublicKeys)
9194
require.NoError(t, err)
95+
err = store.TxRequests().Push(req1.Request, req1.BoardingInputs, req1.CosignersPublicKeys)
96+
require.Contains(t, err.Error(), "duplicated tx request")
97+
err = store.TxRequests().Push(req3.Request, req3.BoardingInputs, req3.CosignersPublicKeys)
98+
require.Contains(t, err.Error(), "duplicated input")
9299
err = store.TxRequests().Push(req2.Request, req2.BoardingInputs, req2.CosignersPublicKeys)
93100
require.NoError(t, err)
94101

server/internal/infrastructure/live-store/redis/intents.go

Lines changed: 20 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@ package redislivestore
22

33
import (
44
"context"
5-
"errors"
65
"fmt"
76
"sort"
87
"time"
@@ -58,56 +57,33 @@ func (s *txRequestsStore) Len() int64 {
5857

5958
func (s *txRequestsStore) Push(request domain.TxRequest, boardingInputs []ports.BoardingInput, cosignerPubkeys []string) error {
6059
ctx := context.Background()
60+
var err error
6161
for attempt := 0; attempt < s.numOfRetries; attempt++ {
62-
err := s.rdb.Watch(ctx, func(tx *redis.Tx) error {
63-
ids, err := tx.SMembers(ctx, txReqStoreReqIdsKey).Result()
64-
if err != nil && !errors.Is(err, redis.Nil) {
65-
return err
66-
}
67-
68-
reqs, err := s.requests.GetMulti(ctx, ids)
62+
err = s.rdb.Watch(ctx, func(tx *redis.Tx) error {
63+
exists, err := tx.SIsMember(ctx, txReqStoreReqIdsKey, request.Id).Result()
6964
if err != nil {
7065
return err
7166
}
72-
73-
if len(reqs) > 0 {
74-
idToReq := make(map[string]*ports.TimedTxRequest, len(ids))
75-
for i, id := range ids {
76-
if reqs[i] != nil {
77-
idToReq[id] = reqs[i]
78-
}
79-
}
80-
81-
if _, exists := idToReq[request.Id]; exists {
82-
return fmt.Errorf("duplicated tx request %s", request.Id)
83-
}
84-
85-
inputMap := make(map[string]string)
86-
boardingInputMap := make(map[string]string)
87-
for _, pay := range idToReq {
88-
for _, pInput := range pay.Inputs {
89-
key := fmt.Sprintf("%s:%d", pInput.Txid, pInput.VOut)
90-
inputMap[key] = pay.Id
91-
}
92-
for _, pBoardingInput := range pay.BoardingInputs {
93-
key := fmt.Sprintf("%s:%d", pBoardingInput.Txid, pBoardingInput.VOut)
94-
boardingInputMap[key] = pay.Id
95-
}
67+
if exists {
68+
return fmt.Errorf("duplicated tx request %s", request.Id)
69+
}
70+
// Check input duplicates directly in Redis set
71+
for _, input := range request.Inputs {
72+
if input.IsNote() {
73+
continue
9674
}
97-
for _, input := range request.Inputs {
98-
key := fmt.Sprintf("%s:%d", input.Txid, input.VOut)
99-
if dupId, exists := inputMap[key]; exists {
100-
return fmt.Errorf("duplicated input, %s already used by tx request %s", key, dupId)
101-
}
75+
key := input.String()
76+
exists, err := tx.SIsMember(ctx, txReqStoreVtxosKey, key).Result()
77+
if err != nil {
78+
return err
10279
}
103-
for _, input := range boardingInputs {
104-
key := fmt.Sprintf("%s:%d", input.Txid, input.VOut)
105-
if dupId, exists := boardingInputMap[key]; exists {
106-
return fmt.Errorf("duplicated boarding input, %s already used by tx request %s", key, dupId)
107-
}
80+
if exists {
81+
return fmt.Errorf("duplicated input, %s already registered by another request", key)
10882
}
10983
}
11084

85+
// Check boarding inputs similarly if you store them
86+
11187
now := time.Now()
11288
timedReq := &ports.TimedTxRequest{
11389
TxRequest: request,
@@ -132,13 +108,13 @@ func (s *txRequestsStore) Push(request domain.TxRequest, boardingInputs []ports.
132108
})
133109

134110
return err
135-
}, txReqStoreReqIdsKey)
111+
}, txReqStoreVtxosKey, txReqStoreReqIdsKey) // WATCH both keys
136112
if err == nil {
137113
return nil
138114
}
139115
time.Sleep(10 * time.Millisecond)
140116
}
141-
return fmt.Errorf("push failed after %v retries", s.numOfRetries)
117+
return err
142118
}
143119

144120
func (s *txRequestsStore) Pop(num int64) []ports.TimedTxRequest {

0 commit comments

Comments
 (0)