Skip to content

Commit 07a3c6b

Browse files
authored
ttx service: create TxAuditor from the TMSID (#1267)
Signed-off-by: Angelo De Caro <adc@zurich.ibm.com>
1 parent 011e4de commit 07a3c6b

File tree

16 files changed

+1114
-57
lines changed

16 files changed

+1114
-57
lines changed

token/sdk/dig/sdk.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,7 @@ import (
5353
"github.com/hyperledger-labs/fabric-token-sdk/token/services/tokens"
5454
"github.com/hyperledger-labs/fabric-token-sdk/token/services/ttx"
5555
"github.com/hyperledger-labs/fabric-token-sdk/token/services/ttx/dep"
56+
auditor2 "github.com/hyperledger-labs/fabric-token-sdk/token/services/ttx/dep/auditor"
5657
wrapper2 "github.com/hyperledger-labs/fabric-token-sdk/token/services/ttx/dep/wrapper"
5758
"github.com/hyperledger-labs/fabric-token-sdk/token/services/ttxdb"
5859
"github.com/hyperledger-labs/fabric-token-sdk/token/services/walletdb"
@@ -174,6 +175,7 @@ func (p *SDK) Install() error {
174175

175176
// ttx service
176177
p.Container().Provide(wrapper2.NewTokenManagementServiceProvider, dig.As(new(dep.TokenManagementServiceProvider))),
178+
p.Container().Provide(wrapper2.NewAuditServiceProvider, dig.As(new(auditor2.ServiceProvider))),
177179
p.Container().Provide(wrapper2.NewNetworkProvider, dig.As(new(dep.NetworkProvider))),
178180
p.Container().Provide(wrapper2.NewNetworkIdentityProvider),
179181
p.Container().Provide(digutils.Identity[*wrapper2.NetworkIdentityProvider](), dig.As(new(dep.NetworkIdentityProvider))),
@@ -225,6 +227,7 @@ func (p *SDK) Install() error {
225227
digutils.Register[dep.NetworkProvider](p.Container()),
226228
digutils.Register[*wrapper2.StorageProvider](p.Container()),
227229
digutils.Register[*wrapper2.NetworkIdentityProvider](p.Container()),
230+
digutils.Register[auditor2.ServiceProvider](p.Container()),
228231
)
229232
if err != nil {
230233
return errors.WithMessagef(err, "failed setting backward comaptibility with SP")

token/services/auditdb/store.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ func NewStoreServiceManager(cp db.ConfigService, drivers multiplexed.Driver) Sto
4545
return db.NewStoreServiceManager(cp, "auditdb.persistence", drivers.NewAuditTransaction, newStoreService)
4646
}
4747

48-
func GetByTMSId(sp token.ServiceProvider, tmsID token.TMSID) (*StoreService, error) {
48+
func GetByTMSID(sp token.ServiceProvider, tmsID token.TMSID) (*StoreService, error) {
4949
s, err := sp.GetService(managerType)
5050
if err != nil {
5151
return nil, errors.Wrapf(err, "failed to get manager service")

token/services/auditor/auditor.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -61,8 +61,8 @@ type CheckService interface {
6161

6262
// Service is the interface for the auditor service
6363
type Service struct {
64-
networkProvider NetworkProvider
6564
tmsID token.TMSID
65+
networkProvider NetworkProvider
6666
auditDB *auditdb.StoreService
6767
tokenDB *tokens.Service
6868
tmsProvider dep.TokenManagementServiceProvider

token/services/auditor/manager.go

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -151,8 +151,3 @@ func GetByTMSID(sp token.ServiceProvider, tmsID token.TMSID) *Service {
151151
}
152152
return auditor
153153
}
154-
155-
// New returns the Service instance for the passed auditor wallet
156-
func New(sp token.ServiceProvider, w *token.AuditorWallet) *Service {
157-
return Get(sp, w)
158-
}

token/services/ttx/auditor.go

Lines changed: 39 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -19,80 +19,80 @@ import (
1919
"github.com/hyperledger-labs/fabric-token-sdk/token/services/auditor"
2020
"github.com/hyperledger-labs/fabric-token-sdk/token/services/db/driver"
2121
"github.com/hyperledger-labs/fabric-token-sdk/token/services/tokens"
22-
"github.com/hyperledger-labs/fabric-token-sdk/token/services/ttxdb"
22+
dauditor "github.com/hyperledger-labs/fabric-token-sdk/token/services/ttx/dep/auditor"
23+
"github.com/hyperledger-labs/fabric-token-sdk/token/services/ttx/dep/db"
2324
"github.com/hyperledger-labs/fabric-token-sdk/token/services/utils"
2425
session2 "github.com/hyperledger-labs/fabric-token-sdk/token/services/utils/json/session"
2526
view3 "github.com/hyperledger-labs/fabric-token-sdk/token/services/utils/view"
2627
)
2728

28-
type TxAuditor struct {
29-
w *token.AuditorWallet
30-
auditor *auditor.Service
31-
auditDB *auditdb.StoreService
32-
transactionInfoProvider *TransactionInfoProvider
29+
// Auditor wraps the functionalities of the auditor service and the audit db for the ttx service
30+
type Auditor struct {
31+
dauditor.Service
32+
dauditor.StoreService
3333
}
3434

35-
func NewAuditor(sp token.ServiceProvider, w *token.AuditorWallet) (*TxAuditor, error) {
36-
backend := auditor.New(sp, w)
37-
auditDB, err := auditdb.GetByTMSId(sp, w.TMS().ID())
35+
// NewAuditorFromTMSID returns a new Auditor for the given TMS ID
36+
func NewAuditorFromTMSID(sp token.ServiceProvider, tmsID token.TMSID) (*Auditor, error) {
37+
auditServiceProvider, err := dauditor.GetServiceProvider(sp)
3838
if err != nil {
39-
return nil, err
39+
return nil, errors.Join(ErrProvider, err)
4040
}
41-
ttxDB, err := ttxdb.GetByTMSId(sp, w.TMS().ID())
41+
auditService, auditStoreService, err := auditServiceProvider.AuditorService(tmsID)
4242
if err != nil {
43-
return nil, err
43+
return nil, errors.Join(ErrProvider, err)
4444
}
45-
return NewTxAuditor(w, backend, auditDB, ttxDB), nil
45+
return &Auditor{
46+
Service: auditService,
47+
StoreService: auditStoreService,
48+
}, nil
4649
}
4750

48-
func NewTxAuditor(w *token.AuditorWallet, backend *auditor.Service, auditDB *auditdb.StoreService, ttxDB *ttxdb.StoreService) *TxAuditor {
49-
return &TxAuditor{
50-
w: w,
51-
auditor: backend,
52-
auditDB: auditDB,
53-
transactionInfoProvider: newTransactionInfoProvider(w.TMS(), ttxDB),
54-
}
51+
// NewAuditor returns a new Auditor for the given wallet.
52+
// This constructor uses NewAuditorFromTMSID with the wallet's TMSID.
53+
func NewAuditor(sp token.ServiceProvider, w *token.AuditorWallet) (*Auditor, error) {
54+
return NewAuditorFromTMSID(sp, w.TMS().ID())
5555
}
5656

57-
func (a *TxAuditor) Validate(tx *Transaction) error {
58-
return a.auditor.Validate(tx.Context, tx.TokenRequest)
57+
func (a *Auditor) Validate(tx *Transaction) error {
58+
return a.Service.Validate(tx.Context, tx.TokenRequest)
5959
}
6060

61-
func (a *TxAuditor) Audit(ctx context.Context, tx *Transaction) (*token.InputStream, *token.OutputStream, error) {
62-
return a.auditor.Audit(ctx, tx)
61+
func (a *Auditor) Audit(ctx context.Context, tx *Transaction) (*token.InputStream, *token.OutputStream, error) {
62+
return a.Service.Audit(ctx, tx)
6363
}
6464

6565
// Release unlocks the passed enrollment IDs.
66-
func (a *TxAuditor) Release(ctx context.Context, tx *Transaction) {
67-
a.auditor.Release(ctx, tx)
66+
func (a *Auditor) Release(ctx context.Context, tx *Transaction) {
67+
a.Service.Release(ctx, tx)
6868
}
6969

7070
// Transactions returns an iterator of transaction records filtered by the given params.
71-
func (a *TxAuditor) Transactions(ctx context.Context, params QueryTransactionsParams, pagination Pagination) (*PageTransactionsIterator, error) {
72-
return a.auditDB.Transactions(ctx, params, pagination)
71+
func (a *Auditor) Transactions(ctx context.Context, params db.QueryTransactionsParams, pagination db.Pagination) (*db.PageTransactionsIterator, error) {
72+
return a.StoreService.Transactions(ctx, params, pagination)
7373
}
7474

7575
// NewPaymentsFilter returns a programmable filter over the payments sent or received by enrollment IDs.
76-
func (a *TxAuditor) NewPaymentsFilter() *auditdb.PaymentsFilter {
77-
return a.auditDB.NewPaymentsFilter()
76+
func (a *Auditor) NewPaymentsFilter() *auditdb.PaymentsFilter {
77+
return a.StoreService.NewPaymentsFilter()
7878
}
7979

8080
// NewHoldingsFilter returns a programmable filter over the holdings owned by enrollment IDs.
81-
func (a *TxAuditor) NewHoldingsFilter() *auditdb.HoldingsFilter {
82-
return a.auditDB.NewHoldingsFilter()
81+
func (a *Auditor) NewHoldingsFilter() *auditdb.HoldingsFilter {
82+
return a.StoreService.NewHoldingsFilter()
8383
}
8484

8585
// SetStatus sets the status of the audit records with the passed transaction id to the passed status
86-
func (a *TxAuditor) SetStatus(ctx context.Context, txID string, status driver.TxStatus, message string) error {
87-
return a.auditDB.SetStatus(ctx, txID, status, message)
86+
func (a *Auditor) SetStatus(ctx context.Context, txID string, status driver.TxStatus, message string) error {
87+
return a.StoreService.SetStatus(ctx, txID, status, message)
8888
}
8989

90-
func (a *TxAuditor) GetTokenRequest(ctx context.Context, txID string) ([]byte, error) {
91-
return a.auditor.GetTokenRequest(ctx, txID)
90+
func (a *Auditor) GetTokenRequest(ctx context.Context, txID string) ([]byte, error) {
91+
return a.Service.GetTokenRequest(ctx, txID)
9292
}
9393

94-
func (a *TxAuditor) Check(ctx context.Context) ([]string, error) {
95-
return a.auditor.Check(ctx)
94+
func (a *Auditor) Check(ctx context.Context) ([]string, error) {
95+
return a.Service.Check(ctx)
9696
}
9797

9898
type RegisterAuditorView struct {
@@ -271,7 +271,7 @@ func NewAuditApproveView(w *token.AuditorWallet, tx *Transaction) *AuditApproveV
271271

272272
func (a *AuditApproveView) Call(context view.Context) (interface{}, error) {
273273
// Append audit records
274-
if err := auditor.New(context, a.w).Append(context.Context(), a.tx); err != nil {
274+
if err := auditor.Get(context, a.w).Append(context.Context(), a.tx); err != nil {
275275
return nil, errors.Wrapf(err, "failed appending audit records for transaction %s", a.tx.ID())
276276
}
277277

token/services/ttx/auditor_test.go

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
/*
2+
Copyright IBM Corp. All Rights Reserved.
3+
4+
SPDX-License-Identifier: Apache-2.0
5+
*/
6+
7+
package ttx_test
8+
9+
import (
10+
"testing"
11+
12+
"github.com/hyperledger-labs/fabric-smart-client/pkg/utils/errors"
13+
"github.com/hyperledger-labs/fabric-token-sdk/token"
14+
"github.com/hyperledger-labs/fabric-token-sdk/token/services/ttx"
15+
mock2 "github.com/hyperledger-labs/fabric-token-sdk/token/services/ttx/dep/auditor/mock"
16+
"github.com/hyperledger-labs/fabric-token-sdk/token/services/ttx/dep/mock"
17+
"github.com/stretchr/testify/assert"
18+
"github.com/stretchr/testify/require"
19+
)
20+
21+
func TestNewAuditorFromTMSID(t *testing.T) {
22+
ctx := &mock.Context{}
23+
tmsID := token.TMSID{
24+
Network: "a_network",
25+
Channel: "a_channel",
26+
Namespace: "a_namespace",
27+
}
28+
29+
// provider failer
30+
ctx.GetServiceReturns(nil, errors.New("service provider error"))
31+
_, err := ttx.NewAuditorFromTMSID(ctx, tmsID)
32+
require.Error(t, err)
33+
assert.ErrorIs(t, err, ttx.ErrProvider)
34+
assert.Contains(t, err.Error(), "service provider error")
35+
36+
// register provider
37+
auditServiceProvider := &mock2.AuditServiceProvider{}
38+
auditServiceProvider.AuditorServiceReturns(nil, nil, errors.New("auditor service error"))
39+
ctx.GetServiceReturns(auditServiceProvider, nil)
40+
_, err = ttx.NewAuditorFromTMSID(ctx, tmsID)
41+
require.Error(t, err)
42+
assert.ErrorIs(t, err, ttx.ErrProvider)
43+
assert.Contains(t, err.Error(), "auditor service error")
44+
45+
auditService := &mock2.AuditService{}
46+
auditStoreService := &mock2.AuditStoreService{}
47+
auditServiceProvider.AuditorServiceReturns(auditService, auditStoreService, nil)
48+
auditor, err := ttx.NewAuditorFromTMSID(ctx, tmsID)
49+
require.NoError(t, err)
50+
assert.NotNil(t, auditor)
51+
assert.Equal(t, auditService, auditor.Service)
52+
assert.Equal(t, auditStoreService, auditor.StoreService)
53+
}

token/services/ttx/db.go

Lines changed: 10 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -10,27 +10,28 @@ import (
1010
"context"
1111

1212
"github.com/hyperledger-labs/fabric-smart-client/pkg/utils/errors"
13-
driver2 "github.com/hyperledger-labs/fabric-smart-client/platform/common/driver"
1413
"github.com/hyperledger-labs/fabric-smart-client/platform/view/services/tracing"
1514
"github.com/hyperledger-labs/fabric-smart-client/platform/view/view"
1615
"github.com/hyperledger-labs/fabric-token-sdk/token"
1716
"github.com/hyperledger-labs/fabric-token-sdk/token/services/db/driver"
1817
"github.com/hyperledger-labs/fabric-token-sdk/token/services/tokens"
1918
"github.com/hyperledger-labs/fabric-token-sdk/token/services/ttx/dep"
19+
"github.com/hyperledger-labs/fabric-token-sdk/token/services/ttx/dep/db"
2020
"github.com/hyperledger-labs/fabric-token-sdk/token/services/ttx/finality"
2121
"github.com/hyperledger-labs/fabric-token-sdk/token/services/ttxdb"
2222
"go.opentelemetry.io/otel/trace"
2323
)
2424

25-
const txIdLabel tracing.LabelName = "tx_id"
26-
27-
type QueryTransactionsParams = ttxdb.QueryTransactionsParams
28-
29-
type Pagination = driver2.Pagination
30-
31-
type TransactionRecord = driver.TransactionRecord
25+
type (
26+
// TransactionRecord is a more finer-grained version of a movement record.
27+
// Given a Token Transaction, for each token action in the Token Request,
28+
// a transaction record is created for each unique enrollment ID found in the outputs.
29+
// The transaction record contains the total amount of the token type that was transferred to/from that enrollment ID
30+
// in that action.
31+
TransactionRecord = db.TransactionRecord
32+
)
3233

33-
type PageTransactionsIterator = driver2.PageIterator[*TransactionRecord]
34+
const txIdLabel tracing.LabelName = "tx_id"
3435

3536
type CheckService interface {
3637
Check(ctx context.Context) ([]string, error)
Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
/*
2+
Copyright IBM Corp. All Rights Reserved.
3+
4+
SPDX-License-Identifier: Apache-2.0
5+
*/
6+
7+
package auditor
8+
9+
import (
10+
"context"
11+
"reflect"
12+
13+
"github.com/hyperledger-labs/fabric-token-sdk/token"
14+
"github.com/hyperledger-labs/fabric-token-sdk/token/driver"
15+
"github.com/hyperledger-labs/fabric-token-sdk/token/services/auditdb"
16+
"github.com/hyperledger-labs/fabric-token-sdk/token/services/auditor"
17+
"github.com/hyperledger-labs/fabric-token-sdk/token/services/ttx/dep/db"
18+
)
19+
20+
var (
21+
serviceProviderType = reflect.TypeOf((*ServiceProvider)(nil))
22+
)
23+
24+
//go:generate counterfeiter -o mock/service.go -fake-name AuditService . Service
25+
26+
// Service models the auditor service
27+
type Service interface {
28+
Validate(ctx context.Context, request *token.Request) error
29+
Audit(ctx context.Context, tx auditor.Transaction) (*token.InputStream, *token.OutputStream, error)
30+
Release(ctx context.Context, tx auditor.Transaction)
31+
GetTokenRequest(ctx context.Context, id string) ([]byte, error)
32+
Check(ctx context.Context) ([]string, error)
33+
}
34+
35+
//go:generate counterfeiter -o mock/store_service.go -fake-name AuditStoreService . StoreService
36+
37+
// StoreService models the audit storage service
38+
type StoreService interface {
39+
Transactions(ctx context.Context, params db.QueryTransactionsParams, pagination db.Pagination) (*db.PageTransactionsIterator, error)
40+
NewPaymentsFilter() *auditdb.PaymentsFilter
41+
NewHoldingsFilter() *auditdb.HoldingsFilter
42+
SetStatus(ctx context.Context, id string, status driver.TxStatus, message string) error
43+
}
44+
45+
//go:generate counterfeiter -o mock/service_provider.go -fake-name AuditServiceProvider . ServiceProvider
46+
47+
// ServiceProvider provides instances of ServiceProvider.
48+
type ServiceProvider interface {
49+
// AuditorService return the auditor service and store service for the given tms id
50+
AuditorService(tmsID token.TMSID) (Service, StoreService, error)
51+
}
52+
53+
// GetServiceProvider retrieves the ServiceProvider from the given ServiceProvider.
54+
func GetServiceProvider(sp token.ServiceProvider) (ServiceProvider, error) {
55+
s, err := sp.GetService(serviceProviderType)
56+
if err != nil {
57+
return nil, err
58+
}
59+
nip, ok := s.(ServiceProvider)
60+
if !ok {
61+
panic("implementation error, type must be ServiceProvider")
62+
}
63+
return nip, nil
64+
}

0 commit comments

Comments
 (0)