/
offledger.go
81 lines (66 loc) · 2.27 KB
/
offledger.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
package services
import (
"errors"
"fmt"
"time"
"github.com/iotaledger/wasp/packages/isc"
"github.com/iotaledger/wasp/packages/peering"
"github.com/iotaledger/wasp/packages/util/expiringcache"
"github.com/iotaledger/wasp/packages/webapi/interfaces"
)
type OffLedgerService struct {
chainService interfaces.ChainService
networkProvider peering.NetworkProvider
requestCache *expiringcache.ExpiringCache[isc.RequestID, bool]
}
func NewOffLedgerService(chainService interfaces.ChainService, networkProvider peering.NetworkProvider, requestCacheTTL time.Duration) interfaces.OffLedgerService {
return &OffLedgerService{
chainService: chainService,
networkProvider: networkProvider,
requestCache: expiringcache.New[isc.RequestID, bool](requestCacheTTL),
}
}
func (c *OffLedgerService) ParseRequest(binaryRequest []byte) (isc.OffLedgerRequest, error) {
// check offledger kind (avoid deserialization otherwise)
if !isc.IsOffledgerKind(binaryRequest[0]) {
return nil, errors.New("error parsing request: off-ledger request expected")
}
request, err := isc.RequestFromBytes(binaryRequest)
if err != nil {
return nil, errors.New("error parsing request from payload")
}
req, ok := request.(isc.OffLedgerRequest)
if !ok {
return nil, errors.New("error parsing request: off-ledger request expected")
}
return req, nil
}
func (c *OffLedgerService) EnqueueOffLedgerRequest(chainID isc.ChainID, binaryRequest []byte) error {
request, err := c.ParseRequest(binaryRequest)
if err != nil {
return err
}
reqID := request.ID()
if c.requestCache.Get(reqID) != nil {
return errors.New("request already processed")
}
// check req signature
if err2 := request.VerifySignature(); err2 != nil {
return fmt.Errorf("could not verify: %w", err2)
}
// check req is for the correct chain
if !request.ChainID().Equals(chainID) {
// do not add to cache, it can still be sent to the correct chain
return errors.New("request is for a different chain")
}
// check chain exists
chain, err := c.chainService.GetChainByID(chainID)
if err != nil {
return err
}
if err := chain.ReceiveOffLedgerRequest(request, c.networkProvider.Self().PubKey()); err != nil {
return fmt.Errorf("tx not added to the mempool: %v", err.Error())
}
c.requestCache.Set(reqID, true)
return nil
}