From deefd25d5b5f2686c4dd3db33d9033984078e69d Mon Sep 17 00:00:00 2001 From: altafan <18440657+altafan@users.noreply.github.com> Date: Wed, 28 Feb 2024 17:27:29 +0100 Subject: [PATCH 1/6] List utxos filtered by addresses --- internal/core/application/account_service.go | 6 ++-- .../core/application/account_service_test.go | 2 +- .../core/application/transaction_service.go | 6 ++-- internal/core/domain/utxo_repository.go | 7 ++-- .../storage/db/badger/utxo_repository.go | 10 ++++-- .../storage/db/inmemory/utxo_repository.go | 34 ++++++++++++++----- .../storage/db/postgres/utxo_repository.go | 27 ++++++++++++--- .../storage/db/test/utxo_repository_test.go | 18 +++++----- internal/interfaces/grpc/handler/account.go | 12 ++++++- 9 files changed, 88 insertions(+), 34 deletions(-) diff --git a/internal/core/application/account_service.go b/internal/core/application/account_service.go index 9465663..f063a72 100644 --- a/internal/core/application/account_service.go +++ b/internal/core/application/account_service.go @@ -160,7 +160,7 @@ func (as *AccountService) GetBalanceForAccount( } func (as *AccountService) ListUtxosForAccount( - ctx context.Context, accountName string, + ctx context.Context, accountName string, scripts [][]byte, ) (*UtxoInfo, error) { w, err := as.repoManager.WalletRepository().GetWallet(ctx) if err != nil { @@ -173,14 +173,14 @@ func (as *AccountService) ListUtxosForAccount( } spendableUtxos, err := as.repoManager.UtxoRepository().GetSpendableUtxosForAccount( - ctx, account.Namespace, + ctx, account.Namespace, scripts, ) if err != nil { return nil, err } lockedUtxos, err := as.repoManager.UtxoRepository().GetLockedUtxosForAccount( - ctx, account.Namespace, + ctx, account.Namespace, scripts, ) if err != nil { return nil, err diff --git a/internal/core/application/account_service_test.go b/internal/core/application/account_service_test.go index f8c615d..cd039a6 100644 --- a/internal/core/application/account_service_test.go +++ b/internal/core/application/account_service_test.go @@ -49,7 +49,7 @@ func TestAccountService(t *testing.T) { require.NoError(t, err) require.GreaterOrEqual(t, len(addresses), 2) - utxos, err := svc.ListUtxosForAccount(ctx, accountName) + utxos, err := svc.ListUtxosForAccount(ctx, accountName, nil) require.NoError(t, err) require.NotNil(t, utxos) require.NotEmpty(t, utxos.Spendable) diff --git a/internal/core/application/transaction_service.go b/internal/core/application/transaction_service.go index 12ce586..9359241 100644 --- a/internal/core/application/transaction_service.go +++ b/internal/core/application/transaction_service.go @@ -105,7 +105,7 @@ func (ts *TransactionService) SelectUtxos( } utxos, err := ts.repoManager.UtxoRepository().GetSpendableUtxosForAccount( - ctx, account.Namespace, + ctx, account.Namespace, nil, ) if err != nil { return nil, 0, -1, err @@ -396,7 +396,7 @@ func (ts *TransactionService) Transfer( } utxos, err := utxoRepo.GetSpendableUtxosForAccount( - ctx, account.Namespace, + ctx, account.Namespace, nil, ) if err != nil { return "", err @@ -778,7 +778,7 @@ func (ts *TransactionService) scheduleUtxoUnlocker() { for accountName := range w.Accounts { utxos, _ := utxoRepo.GetLockedUtxosForAccount( - ctx, accountName, + ctx, accountName, nil, ) if len(utxos) > 0 { utxosToUnlock := make([]domain.UtxoKey, 0, len(utxos)) diff --git a/internal/core/domain/utxo_repository.go b/internal/core/domain/utxo_repository.go index a0cd48b..bb43a28 100644 --- a/internal/core/domain/utxo_repository.go +++ b/internal/core/domain/utxo_repository.go @@ -55,10 +55,11 @@ type UtxoRepository interface { GetAllUtxosForAccount(ctx context.Context, account string) ([]*Utxo, error) // GetSpendableUtxosForAccount returns the list of spendable utxos for the // given account. The list incldues only confirmed and unlocked utxos. - GetSpendableUtxosForAccount(ctx context.Context, account string) ([]*Utxo, error) + // Can be filtered by output scripts. + GetSpendableUtxosForAccount(ctx context.Context, account string, scripts [][]byte) ([]*Utxo, error) // GetLockedUtxosForAccount returns the list of all currently locked utxos - // for the given account. - GetLockedUtxosForAccount(ctx context.Context, account string) ([]*Utxo, error) + // for the given account. Can be filtered by output scripts. + GetLockedUtxosForAccount(ctx context.Context, account string, scripts [][]byte) ([]*Utxo, error) // GetBalanceForAccount returns the confirmed, unconfirmed and locked // balances per each asset for the given account. GetBalanceForAccount(ctx context.Context, account string) (map[string]*Balance, error) diff --git a/internal/infrastructure/storage/db/badger/utxo_repository.go b/internal/infrastructure/storage/db/badger/utxo_repository.go index 403e6a1..e1d0328 100644 --- a/internal/infrastructure/storage/db/badger/utxo_repository.go +++ b/internal/infrastructure/storage/db/badger/utxo_repository.go @@ -83,20 +83,26 @@ func (r *utxoRepository) GetAllUtxosForAccount( } func (r *utxoRepository) GetSpendableUtxosForAccount( - ctx context.Context, accountName string, + ctx context.Context, accountName string, scripts [][]byte, ) ([]*domain.Utxo, error) { query := badgerhold.Where("SpentStatus").Eq(domain.UtxoStatus{}). And("ConfirmedStatus").Ne(domain.UtxoStatus{}). And("LockTimestamp").Eq(int64(0)).And("AccountName").Eq(accountName) + if len(scripts) > 0 { + query = query.And("Script").In(scripts) + } return r.findUtxos(ctx, query) } func (r *utxoRepository) GetLockedUtxosForAccount( - ctx context.Context, accountName string, + ctx context.Context, accountName string, scripts [][]byte, ) ([]*domain.Utxo, error) { query := badgerhold.Where("SpentStatus").Eq(domain.UtxoStatus{}). And("LockTimestamp").Gt(int64(0)).And("AccountName").Eq(accountName) + if len(scripts) > 0 { + query = query.And("Script").In(scripts) + } return r.findUtxos(ctx, query) } diff --git a/internal/infrastructure/storage/db/inmemory/utxo_repository.go b/internal/infrastructure/storage/db/inmemory/utxo_repository.go index fbfdb54..ad86b7f 100644 --- a/internal/infrastructure/storage/db/inmemory/utxo_repository.go +++ b/internal/infrastructure/storage/db/inmemory/utxo_repository.go @@ -1,6 +1,7 @@ package inmemory import ( + "bytes" "context" "sync" @@ -84,25 +85,25 @@ func (r *utxoRepository) GetAllUtxosForAccount( r.store.lock.RLock() defer r.store.lock.RUnlock() - return r.getUtxosForAccount(account, false, false) + return r.getUtxosForAccount(account, false, false, nil) } func (r *utxoRepository) GetSpendableUtxosForAccount( - _ context.Context, account string, + _ context.Context, account string, scripts [][]byte, ) ([]*domain.Utxo, error) { r.store.lock.RLock() defer r.store.lock.RUnlock() - return r.getUtxosForAccount(account, true, false) + return r.getUtxosForAccount(account, true, false, scripts) } func (r *utxoRepository) GetLockedUtxosForAccount( - _ context.Context, account string, + _ context.Context, account string, scripts [][]byte, ) ([]*domain.Utxo, error) { r.store.lock.RLock() defer r.store.lock.RUnlock() - return r.getUtxosForAccount(account, false, true) + return r.getUtxosForAccount(account, false, true, scripts) } func (r *utxoRepository) GetBalanceForAccount( @@ -111,7 +112,7 @@ func (r *utxoRepository) GetBalanceForAccount( r.store.lock.RLock() defer r.store.lock.RUnlock() - utxos, _ := r.getUtxosForAccount(account, false, false) + utxos, _ := r.getUtxosForAccount(account, false, false, nil) balance := make(map[string]*domain.Balance) for _, u := range utxos { if u.IsSpent() { @@ -239,7 +240,7 @@ func (r *utxoRepository) getUtxos(spendableOnly bool) []*domain.Utxo { } func (r *utxoRepository) getUtxosForAccount( - account string, spendableOnly, lockedOnly bool, + account string, spendableOnly, lockedOnly bool, scripts [][]byte, ) ([]*domain.Utxo, error) { keys := r.store.utxosByAccount[account] if len(keys) == 0 { @@ -266,7 +267,24 @@ func (r *utxoRepository) getUtxosForAccount( utxos = append(utxos, u) } - return utxos, nil + if len(scripts) <= 0 { + return utxos, nil + } + + filteredUtxos := make([]*domain.Utxo, 0, len(utxos)) + for _, u := range utxos { + found := false + for _, script := range scripts { + if bytes.Equal(u.Script, script) { + found = true + break + } + } + if found { + filteredUtxos = append(filteredUtxos, u) + } + } + return filteredUtxos, nil } func (r *utxoRepository) spendUtxos( diff --git a/internal/infrastructure/storage/db/postgres/utxo_repository.go b/internal/infrastructure/storage/db/postgres/utxo_repository.go index ad9eb65..76f9cd0 100644 --- a/internal/infrastructure/storage/db/postgres/utxo_repository.go +++ b/internal/infrastructure/storage/db/postgres/utxo_repository.go @@ -1,6 +1,7 @@ package postgresdb import ( + "bytes" "context" "database/sql" "sync" @@ -268,7 +269,7 @@ func (u *utxoRepositoryPg) GetAllUtxosForAccount( } func (u *utxoRepositoryPg) GetSpendableUtxosForAccount( - ctx context.Context, account string, + ctx context.Context, account string, scripts [][]byte, ) ([]*domain.Utxo, error) { resp := make([]*domain.Utxo, 0) utxos, err := u.querier.GetUtxosForAccount(ctx, account) @@ -292,7 +293,16 @@ func (u *utxoRepositoryPg) GetSpendableUtxosForAccount( for _, v := range utxosByKey { if !v.IsLocked() && v.IsConfirmed() && !v.IsSpent() { - resp = append(resp, v) + found := len(scripts) <= 0 + for _, script := range scripts { + if bytes.Equal(v.Script, script) { + found = true + break + } + } + if found { + resp = append(resp, v) + } } } @@ -300,7 +310,7 @@ func (u *utxoRepositoryPg) GetSpendableUtxosForAccount( } func (u *utxoRepositoryPg) GetLockedUtxosForAccount( - ctx context.Context, account string, + ctx context.Context, account string, scripts [][]byte, ) ([]*domain.Utxo, error) { resp := make([]*domain.Utxo, 0) utxos, err := u.querier.GetUtxosForAccount(ctx, account) @@ -324,7 +334,16 @@ func (u *utxoRepositoryPg) GetLockedUtxosForAccount( for _, v := range utxosByKey { if v.IsLocked() { - resp = append(resp, v) + found := len(scripts) <= 0 + for _, script := range scripts { + if bytes.Equal(v.Script, script) { + found = true + break + } + } + if found { + resp = append(resp, v) + } } } diff --git a/internal/infrastructure/storage/db/test/utxo_repository_test.go b/internal/infrastructure/storage/db/test/utxo_repository_test.go index deb6531..5d06909 100644 --- a/internal/infrastructure/storage/db/test/utxo_repository_test.go +++ b/internal/infrastructure/storage/db/test/utxo_repository_test.go @@ -82,11 +82,11 @@ func testAddAndGetUtxos(t *testing.T, repo domain.UtxoRepository) { require.NoError(t, err) require.Empty(t, utxos) - utxos, err = repo.GetSpendableUtxosForAccount(ctx, accountName) + utxos, err = repo.GetSpendableUtxosForAccount(ctx, accountName, nil) require.NoError(t, err) require.Empty(t, utxos) - utxos, err = repo.GetLockedUtxosForAccount(ctx, accountName) + utxos, err = repo.GetLockedUtxosForAccount(ctx, accountName, nil) require.NoError(t, err) require.Empty(t, utxos) @@ -140,7 +140,7 @@ func testConfirmUtxos(t *testing.T, repo domain.UtxoRepository) { require.NoError(t, err) require.Len(t, utxos, len(newUtxos)) - utxos, err = repo.GetSpendableUtxosForAccount(ctx, accountName) + utxos, err = repo.GetSpendableUtxosForAccount(ctx, accountName, nil) require.NoError(t, err) require.Len(t, utxos, len(newUtxos)) @@ -166,7 +166,7 @@ func testLockUtxos(t *testing.T, repo domain.UtxoRepository) { require.NoError(t, err) require.Zero(t, count) - utxos, err := repo.GetLockedUtxosForAccount(ctx, accountName) + utxos, err := repo.GetLockedUtxosForAccount(ctx, accountName, nil) require.NoError(t, err) require.Len(t, utxos, len(newUtxos)) @@ -174,7 +174,7 @@ func testLockUtxos(t *testing.T, repo domain.UtxoRepository) { require.NoError(t, err) require.Empty(t, utxos) - utxos, err = repo.GetSpendableUtxosForAccount(ctx, accountName) + utxos, err = repo.GetSpendableUtxosForAccount(ctx, accountName, nil) require.NoError(t, err) require.Empty(t, utxos) @@ -200,7 +200,7 @@ func testUnlockUtxos(t *testing.T, repo domain.UtxoRepository) { require.NoError(t, err) require.Zero(t, count) - utxos, err := repo.GetLockedUtxosForAccount(ctx, accountName) + utxos, err := repo.GetLockedUtxosForAccount(ctx, accountName, nil) require.NoError(t, err) require.Empty(t, utxos) @@ -208,7 +208,7 @@ func testUnlockUtxos(t *testing.T, repo domain.UtxoRepository) { require.NoError(t, err) require.Len(t, utxos, len(newUtxos)) - utxos, err = repo.GetSpendableUtxosForAccount(ctx, accountName) + utxos, err = repo.GetSpendableUtxosForAccount(ctx, accountName, nil) require.NoError(t, err) require.Len(t, utxos, len(newUtxos)) @@ -238,7 +238,7 @@ func testSpendUtxos(t *testing.T, repo domain.UtxoRepository) { require.NoError(t, err) require.Empty(t, utxos) - utxos, err = repo.GetSpendableUtxosForAccount(ctx, accountName) + utxos, err = repo.GetSpendableUtxosForAccount(ctx, accountName, nil) require.NoError(t, err) require.Empty(t, utxos) @@ -268,7 +268,7 @@ func testConfirmSpentUtxos(t *testing.T, repo domain.UtxoRepository) { require.NoError(t, err) require.Empty(t, utxos) - utxos, err = repo.GetSpendableUtxosForAccount(ctx, accountName) + utxos, err = repo.GetSpendableUtxosForAccount(ctx, accountName, nil) require.NoError(t, err) require.Empty(t, utxos) diff --git a/internal/interfaces/grpc/handler/account.go b/internal/interfaces/grpc/handler/account.go index 421c6fb..a26f94d 100644 --- a/internal/interfaces/grpc/handler/account.go +++ b/internal/interfaces/grpc/handler/account.go @@ -4,6 +4,7 @@ import ( "context" "fmt" + "github.com/vulpemventures/go-elements/address" pb "github.com/vulpemventures/ocean/api-spec/protobuf/gen/go/ocean/v1" "github.com/vulpemventures/ocean/internal/core/application" "google.golang.org/grpc/codes" @@ -173,8 +174,17 @@ func (a *account) ListUtxos( if err != nil { return nil, status.Error(codes.InvalidArgument, err.Error()) } + addresses := req.GetAddresses() + scripts := make([][]byte, 0, len(addresses)) + for _, addr := range addresses { + script, err := address.ToOutputScript(addr) + if err != nil { + return nil, status.Error(codes.InvalidArgument, fmt.Sprintf("invalid address %s", addr)) + } + scripts = append(scripts, script) + } - utxosInfo, err := a.appSvc.ListUtxosForAccount(ctx, name) + utxosInfo, err := a.appSvc.ListUtxosForAccount(ctx, name, scripts) if err != nil { return nil, err } From 565672914aace5d23e29b76f3dbf8d5deda362b4 Mon Sep 17 00:00:00 2001 From: altafan <18440657+altafan@users.noreply.github.com> Date: Wed, 28 Feb 2024 17:53:07 +0100 Subject: [PATCH 2/6] Fix --- .../storage/db/badger/utxo_repository.go | 43 ++++++++++++++++--- 1 file changed, 37 insertions(+), 6 deletions(-) diff --git a/internal/infrastructure/storage/db/badger/utxo_repository.go b/internal/infrastructure/storage/db/badger/utxo_repository.go index e1d0328..e181655 100644 --- a/internal/infrastructure/storage/db/badger/utxo_repository.go +++ b/internal/infrastructure/storage/db/badger/utxo_repository.go @@ -1,6 +1,7 @@ package dbbadger import ( + "bytes" "context" "fmt" "sync" @@ -88,11 +89,26 @@ func (r *utxoRepository) GetSpendableUtxosForAccount( query := badgerhold.Where("SpentStatus").Eq(domain.UtxoStatus{}). And("ConfirmedStatus").Ne(domain.UtxoStatus{}). And("LockTimestamp").Eq(int64(0)).And("AccountName").Eq(accountName) - if len(scripts) > 0 { - query = query.And("Script").In(scripts) + + utxos, err := r.findUtxos(ctx, query) + if err != nil { + return nil, err } - return r.findUtxos(ctx, query) + if len(scripts) <= 0 { + return utxos, nil + } + + filteredUtxos := make([]*domain.Utxo, 0, len(utxos)) + for _, u := range utxos { + for _, script := range scripts { + if bytes.Equal(u.Script, script) { + filteredUtxos = append(filteredUtxos, u) + break + } + } + } + return filteredUtxos, nil } func (r *utxoRepository) GetLockedUtxosForAccount( @@ -100,11 +116,26 @@ func (r *utxoRepository) GetLockedUtxosForAccount( ) ([]*domain.Utxo, error) { query := badgerhold.Where("SpentStatus").Eq(domain.UtxoStatus{}). And("LockTimestamp").Gt(int64(0)).And("AccountName").Eq(accountName) - if len(scripts) > 0 { - query = query.And("Script").In(scripts) + + utxos, err := r.findUtxos(ctx, query) + if err != nil { + return nil, err } - return r.findUtxos(ctx, query) + if len(scripts) <= 0 { + return utxos, nil + } + + filteredUtxos := make([]*domain.Utxo, 0, len(utxos)) + for _, u := range utxos { + for _, script := range scripts { + if bytes.Equal(u.Script, script) { + filteredUtxos = append(filteredUtxos, u) + break + } + } + } + return filteredUtxos, nil } func (r *utxoRepository) GetBalanceForAccount( From b2a08955add51ec9a1418286062c1196579ed569 Mon Sep 17 00:00:00 2001 From: altafan <18440657+altafan@users.noreply.github.com> Date: Wed, 28 Feb 2024 19:37:11 +0100 Subject: [PATCH 3/6] Return unconfirmed utxos --- .../protobuf/gen/go/ocean/v1/account.pb.go | 227 +++++++++--------- api-spec/protobuf/ocean/v1/account.proto | 2 + internal/core/application/account_service.go | 23 +- .../core/application/transaction_service.go | 6 +- internal/core/application/types.go | 5 +- internal/core/domain/utxo_repository.go | 11 +- .../storage/db/badger/utxo_repository.go | 46 ++-- .../storage/db/inmemory/utxo_repository.go | 12 +- .../storage/db/postgres/utxo_repository.go | 39 ++- .../storage/db/test/utxo_repository_test.go | 22 +- internal/interfaces/grpc/handler/account.go | 5 + 11 files changed, 200 insertions(+), 198 deletions(-) diff --git a/api-spec/protobuf/gen/go/ocean/v1/account.pb.go b/api-spec/protobuf/gen/go/ocean/v1/account.pb.go index dc81e7b..a900c59 100644 --- a/api-spec/protobuf/gen/go/ocean/v1/account.pb.go +++ b/api-spec/protobuf/gen/go/ocean/v1/account.pb.go @@ -1011,6 +1011,8 @@ type ListUtxosResponse struct { SpendableUtxos *Utxos `protobuf:"bytes,1,opt,name=spendable_utxos,json=spendableUtxos,proto3" json:"spendable_utxos,omitempty"` // List of currently locked utxos. LockedUtxos *Utxos `protobuf:"bytes,2,opt,name=locked_utxos,json=lockedUtxos,proto3" json:"locked_utxos,omitempty"` + // List of unconfirmed utxos. + UnconfirmedUtxos *Utxos `protobuf:"bytes,3,opt,name=unconfirmed_utxos,json=unconfirmedUtxos,proto3" json:"unconfirmed_utxos,omitempty"` } func (x *ListUtxosResponse) Reset() { @@ -1059,6 +1061,13 @@ func (x *ListUtxosResponse) GetLockedUtxos() *Utxos { return nil } +func (x *ListUtxosResponse) GetUnconfirmedUtxos() *Utxos { + if x != nil { + return x.UnconfirmedUtxos + } + return nil +} + type DeleteAccountRequest struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache @@ -1248,7 +1257,7 @@ var file_ocean_v1_account_proto_rawDesc = []byte{ 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x61, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x1c, 0x0a, 0x09, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x65, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x09, 0x52, 0x09, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, - 0x65, 0x73, 0x22, 0x81, 0x01, 0x0a, 0x11, 0x4c, 0x69, 0x73, 0x74, 0x55, 0x74, 0x78, 0x6f, 0x73, + 0x65, 0x73, 0x22, 0xbf, 0x01, 0x0a, 0x11, 0x4c, 0x69, 0x73, 0x74, 0x55, 0x74, 0x78, 0x6f, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x38, 0x0a, 0x0f, 0x73, 0x70, 0x65, 0x6e, 0x64, 0x61, 0x62, 0x6c, 0x65, 0x5f, 0x75, 0x74, 0x78, 0x6f, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0f, 0x2e, 0x6f, 0x63, 0x65, 0x61, 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x55, 0x74, 0x78, @@ -1256,86 +1265,89 @@ var file_ocean_v1_account_proto_rawDesc = []byte{ 0x6f, 0x73, 0x12, 0x32, 0x0a, 0x0c, 0x6c, 0x6f, 0x63, 0x6b, 0x65, 0x64, 0x5f, 0x75, 0x74, 0x78, 0x6f, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0f, 0x2e, 0x6f, 0x63, 0x65, 0x61, 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x55, 0x74, 0x78, 0x6f, 0x73, 0x52, 0x0b, 0x6c, 0x6f, 0x63, 0x6b, 0x65, - 0x64, 0x55, 0x74, 0x78, 0x6f, 0x73, 0x22, 0x39, 0x0a, 0x14, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, - 0x41, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x21, - 0x0a, 0x0c, 0x61, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, - 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x61, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x4e, 0x61, 0x6d, - 0x65, 0x22, 0x17, 0x0a, 0x15, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x41, 0x63, 0x63, 0x6f, 0x75, - 0x6e, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x32, 0xe4, 0x07, 0x0a, 0x0e, 0x41, - 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x5f, 0x0a, - 0x12, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x41, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x42, 0x49, - 0x50, 0x34, 0x34, 0x12, 0x23, 0x2e, 0x6f, 0x63, 0x65, 0x61, 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x43, + 0x64, 0x55, 0x74, 0x78, 0x6f, 0x73, 0x12, 0x3c, 0x0a, 0x11, 0x75, 0x6e, 0x63, 0x6f, 0x6e, 0x66, + 0x69, 0x72, 0x6d, 0x65, 0x64, 0x5f, 0x75, 0x74, 0x78, 0x6f, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, + 0x0b, 0x32, 0x0f, 0x2e, 0x6f, 0x63, 0x65, 0x61, 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x55, 0x74, 0x78, + 0x6f, 0x73, 0x52, 0x10, 0x75, 0x6e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x72, 0x6d, 0x65, 0x64, 0x55, + 0x74, 0x78, 0x6f, 0x73, 0x22, 0x39, 0x0a, 0x14, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x41, 0x63, + 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x21, 0x0a, 0x0c, + 0x61, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x0b, 0x61, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x4e, 0x61, 0x6d, 0x65, 0x22, + 0x17, 0x0a, 0x15, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x41, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, + 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x32, 0xe4, 0x07, 0x0a, 0x0e, 0x41, 0x63, 0x63, + 0x6f, 0x75, 0x6e, 0x74, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x5f, 0x0a, 0x12, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x41, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x42, 0x49, 0x50, 0x34, - 0x34, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x24, 0x2e, 0x6f, 0x63, 0x65, 0x61, 0x6e, - 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x41, 0x63, 0x63, 0x6f, 0x75, 0x6e, - 0x74, 0x42, 0x49, 0x50, 0x34, 0x34, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x68, - 0x0a, 0x15, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x41, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x4d, - 0x75, 0x6c, 0x74, 0x69, 0x53, 0x69, 0x67, 0x12, 0x26, 0x2e, 0x6f, 0x63, 0x65, 0x61, 0x6e, 0x2e, - 0x76, 0x31, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x41, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, - 0x4d, 0x75, 0x6c, 0x74, 0x69, 0x53, 0x69, 0x67, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, - 0x27, 0x2e, 0x6f, 0x63, 0x65, 0x61, 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, - 0x65, 0x41, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x4d, 0x75, 0x6c, 0x74, 0x69, 0x53, 0x69, 0x67, - 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x62, 0x0a, 0x13, 0x43, 0x72, 0x65, 0x61, - 0x74, 0x65, 0x41, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x43, 0x75, 0x73, 0x74, 0x6f, 0x6d, 0x12, - 0x24, 0x2e, 0x6f, 0x63, 0x65, 0x61, 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, - 0x65, 0x41, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x43, 0x75, 0x73, 0x74, 0x6f, 0x6d, 0x52, 0x65, - 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x25, 0x2e, 0x6f, 0x63, 0x65, 0x61, 0x6e, 0x2e, 0x76, 0x31, - 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x41, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x43, 0x75, - 0x73, 0x74, 0x6f, 0x6d, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x56, 0x0a, 0x0f, - 0x53, 0x65, 0x74, 0x41, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x4c, 0x61, 0x62, 0x65, 0x6c, 0x12, - 0x20, 0x2e, 0x6f, 0x63, 0x65, 0x61, 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x65, 0x74, 0x41, 0x63, - 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x4c, 0x61, 0x62, 0x65, 0x6c, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, - 0x74, 0x1a, 0x21, 0x2e, 0x6f, 0x63, 0x65, 0x61, 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x65, 0x74, - 0x41, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x4c, 0x61, 0x62, 0x65, 0x6c, 0x52, 0x65, 0x73, 0x70, - 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x5f, 0x0a, 0x12, 0x53, 0x65, 0x74, 0x41, 0x63, 0x63, 0x6f, 0x75, - 0x6e, 0x74, 0x54, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x12, 0x23, 0x2e, 0x6f, 0x63, 0x65, - 0x61, 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x65, 0x74, 0x41, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, - 0x54, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, - 0x24, 0x2e, 0x6f, 0x63, 0x65, 0x61, 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x65, 0x74, 0x41, 0x63, - 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x54, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x52, 0x65, 0x73, - 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x56, 0x0a, 0x0f, 0x44, 0x65, 0x72, 0x69, 0x76, 0x65, 0x41, - 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x65, 0x73, 0x12, 0x20, 0x2e, 0x6f, 0x63, 0x65, 0x61, 0x6e, + 0x34, 0x12, 0x23, 0x2e, 0x6f, 0x63, 0x65, 0x61, 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x72, 0x65, + 0x61, 0x74, 0x65, 0x41, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x42, 0x49, 0x50, 0x34, 0x34, 0x52, + 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x24, 0x2e, 0x6f, 0x63, 0x65, 0x61, 0x6e, 0x2e, 0x76, + 0x31, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x41, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x42, + 0x49, 0x50, 0x34, 0x34, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x68, 0x0a, 0x15, + 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x41, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x4d, 0x75, 0x6c, + 0x74, 0x69, 0x53, 0x69, 0x67, 0x12, 0x26, 0x2e, 0x6f, 0x63, 0x65, 0x61, 0x6e, 0x2e, 0x76, 0x31, + 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x41, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x4d, 0x75, + 0x6c, 0x74, 0x69, 0x53, 0x69, 0x67, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x27, 0x2e, + 0x6f, 0x63, 0x65, 0x61, 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x41, + 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x4d, 0x75, 0x6c, 0x74, 0x69, 0x53, 0x69, 0x67, 0x52, 0x65, + 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x62, 0x0a, 0x13, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, + 0x41, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x43, 0x75, 0x73, 0x74, 0x6f, 0x6d, 0x12, 0x24, 0x2e, + 0x6f, 0x63, 0x65, 0x61, 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x41, + 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x43, 0x75, 0x73, 0x74, 0x6f, 0x6d, 0x52, 0x65, 0x71, 0x75, + 0x65, 0x73, 0x74, 0x1a, 0x25, 0x2e, 0x6f, 0x63, 0x65, 0x61, 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x43, + 0x72, 0x65, 0x61, 0x74, 0x65, 0x41, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x43, 0x75, 0x73, 0x74, + 0x6f, 0x6d, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x56, 0x0a, 0x0f, 0x53, 0x65, + 0x74, 0x41, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x4c, 0x61, 0x62, 0x65, 0x6c, 0x12, 0x20, 0x2e, + 0x6f, 0x63, 0x65, 0x61, 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x65, 0x74, 0x41, 0x63, 0x63, 0x6f, + 0x75, 0x6e, 0x74, 0x4c, 0x61, 0x62, 0x65, 0x6c, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, + 0x21, 0x2e, 0x6f, 0x63, 0x65, 0x61, 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x65, 0x74, 0x41, 0x63, + 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x4c, 0x61, 0x62, 0x65, 0x6c, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, + 0x73, 0x65, 0x12, 0x5f, 0x0a, 0x12, 0x53, 0x65, 0x74, 0x41, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, + 0x54, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x12, 0x23, 0x2e, 0x6f, 0x63, 0x65, 0x61, 0x6e, + 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x65, 0x74, 0x41, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x54, 0x65, + 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x24, 0x2e, + 0x6f, 0x63, 0x65, 0x61, 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x65, 0x74, 0x41, 0x63, 0x63, 0x6f, + 0x75, 0x6e, 0x74, 0x54, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, + 0x6e, 0x73, 0x65, 0x12, 0x56, 0x0a, 0x0f, 0x44, 0x65, 0x72, 0x69, 0x76, 0x65, 0x41, 0x64, 0x64, + 0x72, 0x65, 0x73, 0x73, 0x65, 0x73, 0x12, 0x20, 0x2e, 0x6f, 0x63, 0x65, 0x61, 0x6e, 0x2e, 0x76, + 0x31, 0x2e, 0x44, 0x65, 0x72, 0x69, 0x76, 0x65, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x65, + 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x21, 0x2e, 0x6f, 0x63, 0x65, 0x61, 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x44, 0x65, 0x72, 0x69, 0x76, 0x65, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, - 0x73, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x21, 0x2e, 0x6f, 0x63, 0x65, - 0x61, 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x44, 0x65, 0x72, 0x69, 0x76, 0x65, 0x41, 0x64, 0x64, 0x72, - 0x65, 0x73, 0x73, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x68, 0x0a, - 0x15, 0x44, 0x65, 0x72, 0x69, 0x76, 0x65, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x41, 0x64, 0x64, - 0x72, 0x65, 0x73, 0x73, 0x65, 0x73, 0x12, 0x26, 0x2e, 0x6f, 0x63, 0x65, 0x61, 0x6e, 0x2e, 0x76, - 0x31, 0x2e, 0x44, 0x65, 0x72, 0x69, 0x76, 0x65, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x41, 0x64, - 0x64, 0x72, 0x65, 0x73, 0x73, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x27, - 0x2e, 0x6f, 0x63, 0x65, 0x61, 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x44, 0x65, 0x72, 0x69, 0x76, 0x65, - 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x65, 0x73, 0x52, - 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x50, 0x0a, 0x0d, 0x4c, 0x69, 0x73, 0x74, 0x41, - 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x65, 0x73, 0x12, 0x1e, 0x2e, 0x6f, 0x63, 0x65, 0x61, 0x6e, - 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x65, - 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1f, 0x2e, 0x6f, 0x63, 0x65, 0x61, 0x6e, - 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x65, - 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x3e, 0x0a, 0x07, 0x42, 0x61, 0x6c, - 0x61, 0x6e, 0x63, 0x65, 0x12, 0x18, 0x2e, 0x6f, 0x63, 0x65, 0x61, 0x6e, 0x2e, 0x76, 0x31, 0x2e, - 0x42, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x19, - 0x2e, 0x6f, 0x63, 0x65, 0x61, 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x42, 0x61, 0x6c, 0x61, 0x6e, 0x63, - 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x44, 0x0a, 0x09, 0x4c, 0x69, 0x73, - 0x74, 0x55, 0x74, 0x78, 0x6f, 0x73, 0x12, 0x1a, 0x2e, 0x6f, 0x63, 0x65, 0x61, 0x6e, 0x2e, 0x76, - 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x55, 0x74, 0x78, 0x6f, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, - 0x73, 0x74, 0x1a, 0x1b, 0x2e, 0x6f, 0x63, 0x65, 0x61, 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, - 0x73, 0x74, 0x55, 0x74, 0x78, 0x6f, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, - 0x50, 0x0a, 0x0d, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x41, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, - 0x12, 0x1e, 0x2e, 0x6f, 0x63, 0x65, 0x61, 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x44, 0x65, 0x6c, 0x65, - 0x74, 0x65, 0x41, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, - 0x1a, 0x1f, 0x2e, 0x6f, 0x63, 0x65, 0x61, 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x44, 0x65, 0x6c, 0x65, - 0x74, 0x65, 0x41, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, - 0x65, 0x42, 0xa5, 0x01, 0x0a, 0x0c, 0x63, 0x6f, 0x6d, 0x2e, 0x6f, 0x63, 0x65, 0x61, 0x6e, 0x2e, - 0x76, 0x31, 0x42, 0x0c, 0x41, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x50, 0x72, 0x6f, 0x74, 0x6f, - 0x50, 0x01, 0x5a, 0x46, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x76, - 0x75, 0x6c, 0x70, 0x65, 0x6d, 0x76, 0x65, 0x6e, 0x74, 0x75, 0x72, 0x65, 0x73, 0x2f, 0x6f, 0x63, - 0x65, 0x61, 0x6e, 0x2f, 0x61, 0x70, 0x69, 0x2d, 0x73, 0x70, 0x65, 0x63, 0x2f, 0x70, 0x72, 0x6f, - 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2f, 0x67, 0x65, 0x6e, 0x2f, 0x6f, 0x63, 0x65, 0x61, 0x6e, 0x2f, - 0x76, 0x31, 0x3b, 0x6f, 0x63, 0x65, 0x61, 0x6e, 0x76, 0x31, 0xa2, 0x02, 0x03, 0x4f, 0x58, 0x58, - 0xaa, 0x02, 0x08, 0x4f, 0x63, 0x65, 0x61, 0x6e, 0x2e, 0x56, 0x31, 0xca, 0x02, 0x08, 0x4f, 0x63, - 0x65, 0x61, 0x6e, 0x5c, 0x56, 0x31, 0xe2, 0x02, 0x14, 0x4f, 0x63, 0x65, 0x61, 0x6e, 0x5c, 0x56, - 0x31, 0x5c, 0x47, 0x50, 0x42, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0xea, 0x02, 0x09, - 0x4f, 0x63, 0x65, 0x61, 0x6e, 0x3a, 0x3a, 0x56, 0x31, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, - 0x33, + 0x73, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x68, 0x0a, 0x15, 0x44, + 0x65, 0x72, 0x69, 0x76, 0x65, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x41, 0x64, 0x64, 0x72, 0x65, + 0x73, 0x73, 0x65, 0x73, 0x12, 0x26, 0x2e, 0x6f, 0x63, 0x65, 0x61, 0x6e, 0x2e, 0x76, 0x31, 0x2e, + 0x44, 0x65, 0x72, 0x69, 0x76, 0x65, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x41, 0x64, 0x64, 0x72, + 0x65, 0x73, 0x73, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x27, 0x2e, 0x6f, + 0x63, 0x65, 0x61, 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x44, 0x65, 0x72, 0x69, 0x76, 0x65, 0x43, 0x68, + 0x61, 0x6e, 0x67, 0x65, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x65, 0x73, 0x52, 0x65, 0x73, + 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x50, 0x0a, 0x0d, 0x4c, 0x69, 0x73, 0x74, 0x41, 0x64, 0x64, + 0x72, 0x65, 0x73, 0x73, 0x65, 0x73, 0x12, 0x1e, 0x2e, 0x6f, 0x63, 0x65, 0x61, 0x6e, 0x2e, 0x76, + 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x65, 0x73, 0x52, + 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1f, 0x2e, 0x6f, 0x63, 0x65, 0x61, 0x6e, 0x2e, 0x76, + 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x65, 0x73, 0x52, + 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x3e, 0x0a, 0x07, 0x42, 0x61, 0x6c, 0x61, 0x6e, + 0x63, 0x65, 0x12, 0x18, 0x2e, 0x6f, 0x63, 0x65, 0x61, 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x42, 0x61, + 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x19, 0x2e, 0x6f, + 0x63, 0x65, 0x61, 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x42, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x52, + 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x44, 0x0a, 0x09, 0x4c, 0x69, 0x73, 0x74, 0x55, + 0x74, 0x78, 0x6f, 0x73, 0x12, 0x1a, 0x2e, 0x6f, 0x63, 0x65, 0x61, 0x6e, 0x2e, 0x76, 0x31, 0x2e, + 0x4c, 0x69, 0x73, 0x74, 0x55, 0x74, 0x78, 0x6f, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, + 0x1a, 0x1b, 0x2e, 0x6f, 0x63, 0x65, 0x61, 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, + 0x55, 0x74, 0x78, 0x6f, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x50, 0x0a, + 0x0d, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x41, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x1e, + 0x2e, 0x6f, 0x63, 0x65, 0x61, 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, + 0x41, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1f, + 0x2e, 0x6f, 0x63, 0x65, 0x61, 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, + 0x41, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x42, + 0xa5, 0x01, 0x0a, 0x0c, 0x63, 0x6f, 0x6d, 0x2e, 0x6f, 0x63, 0x65, 0x61, 0x6e, 0x2e, 0x76, 0x31, + 0x42, 0x0c, 0x41, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01, + 0x5a, 0x46, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x76, 0x75, 0x6c, + 0x70, 0x65, 0x6d, 0x76, 0x65, 0x6e, 0x74, 0x75, 0x72, 0x65, 0x73, 0x2f, 0x6f, 0x63, 0x65, 0x61, + 0x6e, 0x2f, 0x61, 0x70, 0x69, 0x2d, 0x73, 0x70, 0x65, 0x63, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, + 0x62, 0x75, 0x66, 0x2f, 0x67, 0x65, 0x6e, 0x2f, 0x6f, 0x63, 0x65, 0x61, 0x6e, 0x2f, 0x76, 0x31, + 0x3b, 0x6f, 0x63, 0x65, 0x61, 0x6e, 0x76, 0x31, 0xa2, 0x02, 0x03, 0x4f, 0x58, 0x58, 0xaa, 0x02, + 0x08, 0x4f, 0x63, 0x65, 0x61, 0x6e, 0x2e, 0x56, 0x31, 0xca, 0x02, 0x08, 0x4f, 0x63, 0x65, 0x61, + 0x6e, 0x5c, 0x56, 0x31, 0xe2, 0x02, 0x14, 0x4f, 0x63, 0x65, 0x61, 0x6e, 0x5c, 0x56, 0x31, 0x5c, + 0x47, 0x50, 0x42, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0xea, 0x02, 0x09, 0x4f, 0x63, + 0x65, 0x61, 0x6e, 0x3a, 0x3a, 0x56, 0x31, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( @@ -1389,34 +1401,35 @@ var file_ocean_v1_account_proto_depIdxs = []int32{ 22, // 5: ocean.v1.BalanceResponse.balance:type_name -> ocean.v1.BalanceResponse.BalanceEntry 25, // 6: ocean.v1.ListUtxosResponse.spendable_utxos:type_name -> ocean.v1.Utxos 25, // 7: ocean.v1.ListUtxosResponse.locked_utxos:type_name -> ocean.v1.Utxos - 26, // 8: ocean.v1.BalanceResponse.BalanceEntry.value:type_name -> ocean.v1.BalanceInfo - 0, // 9: ocean.v1.AccountService.CreateAccountBIP44:input_type -> ocean.v1.CreateAccountBIP44Request - 2, // 10: ocean.v1.AccountService.CreateAccountMultiSig:input_type -> ocean.v1.CreateAccountMultiSigRequest - 4, // 11: ocean.v1.AccountService.CreateAccountCustom:input_type -> ocean.v1.CreateAccountCustomRequest - 6, // 12: ocean.v1.AccountService.SetAccountLabel:input_type -> ocean.v1.SetAccountLabelRequest - 8, // 13: ocean.v1.AccountService.SetAccountTemplate:input_type -> ocean.v1.SetAccountTemplateRequest - 10, // 14: ocean.v1.AccountService.DeriveAddresses:input_type -> ocean.v1.DeriveAddressesRequest - 12, // 15: ocean.v1.AccountService.DeriveChangeAddresses:input_type -> ocean.v1.DeriveChangeAddressesRequest - 14, // 16: ocean.v1.AccountService.ListAddresses:input_type -> ocean.v1.ListAddressesRequest - 16, // 17: ocean.v1.AccountService.Balance:input_type -> ocean.v1.BalanceRequest - 18, // 18: ocean.v1.AccountService.ListUtxos:input_type -> ocean.v1.ListUtxosRequest - 20, // 19: ocean.v1.AccountService.DeleteAccount:input_type -> ocean.v1.DeleteAccountRequest - 1, // 20: ocean.v1.AccountService.CreateAccountBIP44:output_type -> ocean.v1.CreateAccountBIP44Response - 3, // 21: ocean.v1.AccountService.CreateAccountMultiSig:output_type -> ocean.v1.CreateAccountMultiSigResponse - 5, // 22: ocean.v1.AccountService.CreateAccountCustom:output_type -> ocean.v1.CreateAccountCustomResponse - 7, // 23: ocean.v1.AccountService.SetAccountLabel:output_type -> ocean.v1.SetAccountLabelResponse - 9, // 24: ocean.v1.AccountService.SetAccountTemplate:output_type -> ocean.v1.SetAccountTemplateResponse - 11, // 25: ocean.v1.AccountService.DeriveAddresses:output_type -> ocean.v1.DeriveAddressesResponse - 13, // 26: ocean.v1.AccountService.DeriveChangeAddresses:output_type -> ocean.v1.DeriveChangeAddressesResponse - 15, // 27: ocean.v1.AccountService.ListAddresses:output_type -> ocean.v1.ListAddressesResponse - 17, // 28: ocean.v1.AccountService.Balance:output_type -> ocean.v1.BalanceResponse - 19, // 29: ocean.v1.AccountService.ListUtxos:output_type -> ocean.v1.ListUtxosResponse - 21, // 30: ocean.v1.AccountService.DeleteAccount:output_type -> ocean.v1.DeleteAccountResponse - 20, // [20:31] is the sub-list for method output_type - 9, // [9:20] is the sub-list for method input_type - 9, // [9:9] is the sub-list for extension type_name - 9, // [9:9] is the sub-list for extension extendee - 0, // [0:9] is the sub-list for field type_name + 25, // 8: ocean.v1.ListUtxosResponse.unconfirmed_utxos:type_name -> ocean.v1.Utxos + 26, // 9: ocean.v1.BalanceResponse.BalanceEntry.value:type_name -> ocean.v1.BalanceInfo + 0, // 10: ocean.v1.AccountService.CreateAccountBIP44:input_type -> ocean.v1.CreateAccountBIP44Request + 2, // 11: ocean.v1.AccountService.CreateAccountMultiSig:input_type -> ocean.v1.CreateAccountMultiSigRequest + 4, // 12: ocean.v1.AccountService.CreateAccountCustom:input_type -> ocean.v1.CreateAccountCustomRequest + 6, // 13: ocean.v1.AccountService.SetAccountLabel:input_type -> ocean.v1.SetAccountLabelRequest + 8, // 14: ocean.v1.AccountService.SetAccountTemplate:input_type -> ocean.v1.SetAccountTemplateRequest + 10, // 15: ocean.v1.AccountService.DeriveAddresses:input_type -> ocean.v1.DeriveAddressesRequest + 12, // 16: ocean.v1.AccountService.DeriveChangeAddresses:input_type -> ocean.v1.DeriveChangeAddressesRequest + 14, // 17: ocean.v1.AccountService.ListAddresses:input_type -> ocean.v1.ListAddressesRequest + 16, // 18: ocean.v1.AccountService.Balance:input_type -> ocean.v1.BalanceRequest + 18, // 19: ocean.v1.AccountService.ListUtxos:input_type -> ocean.v1.ListUtxosRequest + 20, // 20: ocean.v1.AccountService.DeleteAccount:input_type -> ocean.v1.DeleteAccountRequest + 1, // 21: ocean.v1.AccountService.CreateAccountBIP44:output_type -> ocean.v1.CreateAccountBIP44Response + 3, // 22: ocean.v1.AccountService.CreateAccountMultiSig:output_type -> ocean.v1.CreateAccountMultiSigResponse + 5, // 23: ocean.v1.AccountService.CreateAccountCustom:output_type -> ocean.v1.CreateAccountCustomResponse + 7, // 24: ocean.v1.AccountService.SetAccountLabel:output_type -> ocean.v1.SetAccountLabelResponse + 9, // 25: ocean.v1.AccountService.SetAccountTemplate:output_type -> ocean.v1.SetAccountTemplateResponse + 11, // 26: ocean.v1.AccountService.DeriveAddresses:output_type -> ocean.v1.DeriveAddressesResponse + 13, // 27: ocean.v1.AccountService.DeriveChangeAddresses:output_type -> ocean.v1.DeriveChangeAddressesResponse + 15, // 28: ocean.v1.AccountService.ListAddresses:output_type -> ocean.v1.ListAddressesResponse + 17, // 29: ocean.v1.AccountService.Balance:output_type -> ocean.v1.BalanceResponse + 19, // 30: ocean.v1.AccountService.ListUtxos:output_type -> ocean.v1.ListUtxosResponse + 21, // 31: ocean.v1.AccountService.DeleteAccount:output_type -> ocean.v1.DeleteAccountResponse + 21, // [21:32] is the sub-list for method output_type + 10, // [10:21] is the sub-list for method input_type + 10, // [10:10] is the sub-list for extension type_name + 10, // [10:10] is the sub-list for extension extendee + 0, // [0:10] is the sub-list for field type_name } func init() { file_ocean_v1_account_proto_init() } diff --git a/api-spec/protobuf/ocean/v1/account.proto b/api-spec/protobuf/ocean/v1/account.proto index 47b5d99..da6193f 100644 --- a/api-spec/protobuf/ocean/v1/account.proto +++ b/api-spec/protobuf/ocean/v1/account.proto @@ -150,6 +150,8 @@ message ListUtxosResponse{ Utxos spendable_utxos = 1; // List of currently locked utxos. Utxos locked_utxos = 2; + // List of unconfirmed utxos. + Utxos unconfirmed_utxos = 3; } message DeleteAccountRequest{ diff --git a/internal/core/application/account_service.go b/internal/core/application/account_service.go index f063a72..854e34a 100644 --- a/internal/core/application/account_service.go +++ b/internal/core/application/account_service.go @@ -172,21 +172,30 @@ func (as *AccountService) ListUtxosForAccount( return nil, err } - spendableUtxos, err := as.repoManager.UtxoRepository().GetSpendableUtxosForAccount( + utxos, err := as.repoManager.UtxoRepository().GetAllUtxosForAccount( ctx, account.Namespace, scripts, ) if err != nil { return nil, err } - lockedUtxos, err := as.repoManager.UtxoRepository().GetLockedUtxosForAccount( - ctx, account.Namespace, scripts, - ) - if err != nil { - return nil, err + spendableUtxos := make([]*domain.Utxo, 0, len(utxos)) + unconfirmedUtxos := make([]*domain.Utxo, 0, len(utxos)) + lockedUtxos := make([]*domain.Utxo, 0, len(utxos)) + + for _, u := range utxos { + if u.IsLocked() { + lockedUtxos = append(lockedUtxos, u) + } else { + if u.IsConfirmed() { + spendableUtxos = append(spendableUtxos, u) + } else { + unconfirmedUtxos = append(unconfirmedUtxos, u) + } + } } - return &UtxoInfo{spendableUtxos, lockedUtxos}, nil + return &UtxoInfo{spendableUtxos, lockedUtxos, unconfirmedUtxos}, nil } func (as *AccountService) DeleteAccount( diff --git a/internal/core/application/transaction_service.go b/internal/core/application/transaction_service.go index 9359241..12ce586 100644 --- a/internal/core/application/transaction_service.go +++ b/internal/core/application/transaction_service.go @@ -105,7 +105,7 @@ func (ts *TransactionService) SelectUtxos( } utxos, err := ts.repoManager.UtxoRepository().GetSpendableUtxosForAccount( - ctx, account.Namespace, nil, + ctx, account.Namespace, ) if err != nil { return nil, 0, -1, err @@ -396,7 +396,7 @@ func (ts *TransactionService) Transfer( } utxos, err := utxoRepo.GetSpendableUtxosForAccount( - ctx, account.Namespace, nil, + ctx, account.Namespace, ) if err != nil { return "", err @@ -778,7 +778,7 @@ func (ts *TransactionService) scheduleUtxoUnlocker() { for accountName := range w.Accounts { utxos, _ := utxoRepo.GetLockedUtxosForAccount( - ctx, accountName, nil, + ctx, accountName, ) if len(utxos) > 0 { utxosToUnlock := make([]domain.UtxoKey, 0, len(utxos)) diff --git a/internal/core/application/types.go b/internal/core/application/types.go index 5727b30..e02a49a 100644 --- a/internal/core/application/types.go +++ b/internal/core/application/types.go @@ -55,8 +55,9 @@ type BuildInfo struct { } type UtxoInfo struct { - Spendable Utxos - Locked Utxos + Spendable Utxos + Locked Utxos + Unconfirmed Utxos } type TransactionInfo domain.Transaction diff --git a/internal/core/domain/utxo_repository.go b/internal/core/domain/utxo_repository.go index bb43a28..5e9c1e3 100644 --- a/internal/core/domain/utxo_repository.go +++ b/internal/core/domain/utxo_repository.go @@ -51,15 +51,14 @@ type UtxoRepository interface { // GetSpendableUtxos returns all unlocked utxo UTXOs. GetSpendableUtxos(ctx context.Context) ([]*Utxo, error) // GetAllUtxosForAccount returns the list of all utxos for the given - // account. - GetAllUtxosForAccount(ctx context.Context, account string) ([]*Utxo, error) + // account. Can be filtered by output scripts. + GetAllUtxosForAccount(ctx context.Context, account string, scripts [][]byte) ([]*Utxo, error) // GetSpendableUtxosForAccount returns the list of spendable utxos for the // given account. The list incldues only confirmed and unlocked utxos. - // Can be filtered by output scripts. - GetSpendableUtxosForAccount(ctx context.Context, account string, scripts [][]byte) ([]*Utxo, error) + GetSpendableUtxosForAccount(ctx context.Context, account string) ([]*Utxo, error) // GetLockedUtxosForAccount returns the list of all currently locked utxos - // for the given account. Can be filtered by output scripts. - GetLockedUtxosForAccount(ctx context.Context, account string, scripts [][]byte) ([]*Utxo, error) + // for the given account. + GetLockedUtxosForAccount(ctx context.Context, account string) ([]*Utxo, error) // GetBalanceForAccount returns the confirmed, unconfirmed and locked // balances per each asset for the given account. GetBalanceForAccount(ctx context.Context, account string) (map[string]*Balance, error) diff --git a/internal/infrastructure/storage/db/badger/utxo_repository.go b/internal/infrastructure/storage/db/badger/utxo_repository.go index e181655..a0d31a7 100644 --- a/internal/infrastructure/storage/db/badger/utxo_repository.go +++ b/internal/infrastructure/storage/db/badger/utxo_repository.go @@ -76,19 +76,9 @@ func (r *utxoRepository) GetSpendableUtxos( } func (r *utxoRepository) GetAllUtxosForAccount( - ctx context.Context, accountName string, -) ([]*domain.Utxo, error) { - query := badgerhold.Where("AccountName").Eq(accountName) - - return r.findUtxos(ctx, query) -} - -func (r *utxoRepository) GetSpendableUtxosForAccount( ctx context.Context, accountName string, scripts [][]byte, ) ([]*domain.Utxo, error) { - query := badgerhold.Where("SpentStatus").Eq(domain.UtxoStatus{}). - And("ConfirmedStatus").Ne(domain.UtxoStatus{}). - And("LockTimestamp").Eq(int64(0)).And("AccountName").Eq(accountName) + query := badgerhold.Where("AccountName").Eq(accountName) utxos, err := r.findUtxos(ctx, query) if err != nil { @@ -111,37 +101,29 @@ func (r *utxoRepository) GetSpendableUtxosForAccount( return filteredUtxos, nil } -func (r *utxoRepository) GetLockedUtxosForAccount( - ctx context.Context, accountName string, scripts [][]byte, +func (r *utxoRepository) GetSpendableUtxosForAccount( + ctx context.Context, accountName string, ) ([]*domain.Utxo, error) { query := badgerhold.Where("SpentStatus").Eq(domain.UtxoStatus{}). - And("LockTimestamp").Gt(int64(0)).And("AccountName").Eq(accountName) + And("ConfirmedStatus").Ne(domain.UtxoStatus{}). + And("LockTimestamp").Eq(int64(0)).And("AccountName").Eq(accountName) - utxos, err := r.findUtxos(ctx, query) - if err != nil { - return nil, err - } + return r.findUtxos(ctx, query) +} - if len(scripts) <= 0 { - return utxos, nil - } +func (r *utxoRepository) GetLockedUtxosForAccount( + ctx context.Context, accountName string, +) ([]*domain.Utxo, error) { + query := badgerhold.Where("SpentStatus").Eq(domain.UtxoStatus{}). + And("LockTimestamp").Gt(int64(0)).And("AccountName").Eq(accountName) - filteredUtxos := make([]*domain.Utxo, 0, len(utxos)) - for _, u := range utxos { - for _, script := range scripts { - if bytes.Equal(u.Script, script) { - filteredUtxos = append(filteredUtxos, u) - break - } - } - } - return filteredUtxos, nil + return r.findUtxos(ctx, query) } func (r *utxoRepository) GetBalanceForAccount( ctx context.Context, accountName string, ) (map[string]*domain.Balance, error) { - utxos, err := r.GetAllUtxosForAccount(ctx, accountName) + utxos, err := r.GetAllUtxosForAccount(ctx, accountName, nil) if err != nil { return nil, err } diff --git a/internal/infrastructure/storage/db/inmemory/utxo_repository.go b/internal/infrastructure/storage/db/inmemory/utxo_repository.go index ad86b7f..d2f5e29 100644 --- a/internal/infrastructure/storage/db/inmemory/utxo_repository.go +++ b/internal/infrastructure/storage/db/inmemory/utxo_repository.go @@ -80,30 +80,30 @@ func (r *utxoRepository) GetSpendableUtxos(_ context.Context) ([]*domain.Utxo, e } func (r *utxoRepository) GetAllUtxosForAccount( - _ context.Context, account string, + _ context.Context, account string, scripts [][]byte, ) ([]*domain.Utxo, error) { r.store.lock.RLock() defer r.store.lock.RUnlock() - return r.getUtxosForAccount(account, false, false, nil) + return r.getUtxosForAccount(account, false, false, scripts) } func (r *utxoRepository) GetSpendableUtxosForAccount( - _ context.Context, account string, scripts [][]byte, + _ context.Context, account string, ) ([]*domain.Utxo, error) { r.store.lock.RLock() defer r.store.lock.RUnlock() - return r.getUtxosForAccount(account, true, false, scripts) + return r.getUtxosForAccount(account, true, false, nil) } func (r *utxoRepository) GetLockedUtxosForAccount( - _ context.Context, account string, scripts [][]byte, + _ context.Context, account string, ) ([]*domain.Utxo, error) { r.store.lock.RLock() defer r.store.lock.RUnlock() - return r.getUtxosForAccount(account, false, true, scripts) + return r.getUtxosForAccount(account, false, true, nil) } func (r *utxoRepository) GetBalanceForAccount( diff --git a/internal/infrastructure/storage/db/postgres/utxo_repository.go b/internal/infrastructure/storage/db/postgres/utxo_repository.go index 76f9cd0..31f3247 100644 --- a/internal/infrastructure/storage/db/postgres/utxo_repository.go +++ b/internal/infrastructure/storage/db/postgres/utxo_repository.go @@ -239,7 +239,7 @@ func (u *utxoRepositoryPg) GetSpendableUtxos( } func (u *utxoRepositoryPg) GetAllUtxosForAccount( - ctx context.Context, account string, + ctx context.Context, account string, scripts [][]byte, ) ([]*domain.Utxo, error) { resp := make([]*domain.Utxo, 0) utxos, err := u.querier.GetUtxosForAccount(ctx, account) @@ -262,14 +262,23 @@ func (u *utxoRepositoryPg) GetAllUtxosForAccount( } for _, v := range utxosByKey { - resp = append(resp, v) + found := len(scripts) <= 0 + for _, script := range scripts { + if bytes.Equal(v.Script, script) { + found = true + break + } + } + if found { + resp = append(resp, v) + } } return resp, nil } func (u *utxoRepositoryPg) GetSpendableUtxosForAccount( - ctx context.Context, account string, scripts [][]byte, + ctx context.Context, account string, ) ([]*domain.Utxo, error) { resp := make([]*domain.Utxo, 0) utxos, err := u.querier.GetUtxosForAccount(ctx, account) @@ -293,16 +302,7 @@ func (u *utxoRepositoryPg) GetSpendableUtxosForAccount( for _, v := range utxosByKey { if !v.IsLocked() && v.IsConfirmed() && !v.IsSpent() { - found := len(scripts) <= 0 - for _, script := range scripts { - if bytes.Equal(v.Script, script) { - found = true - break - } - } - if found { - resp = append(resp, v) - } + resp = append(resp, v) } } @@ -310,7 +310,7 @@ func (u *utxoRepositoryPg) GetSpendableUtxosForAccount( } func (u *utxoRepositoryPg) GetLockedUtxosForAccount( - ctx context.Context, account string, scripts [][]byte, + ctx context.Context, account string, ) ([]*domain.Utxo, error) { resp := make([]*domain.Utxo, 0) utxos, err := u.querier.GetUtxosForAccount(ctx, account) @@ -334,16 +334,7 @@ func (u *utxoRepositoryPg) GetLockedUtxosForAccount( for _, v := range utxosByKey { if v.IsLocked() { - found := len(scripts) <= 0 - for _, script := range scripts { - if bytes.Equal(v.Script, script) { - found = true - break - } - } - if found { - resp = append(resp, v) - } + resp = append(resp, v) } } diff --git a/internal/infrastructure/storage/db/test/utxo_repository_test.go b/internal/infrastructure/storage/db/test/utxo_repository_test.go index 5d06909..8db818c 100644 --- a/internal/infrastructure/storage/db/test/utxo_repository_test.go +++ b/internal/infrastructure/storage/db/test/utxo_repository_test.go @@ -70,11 +70,11 @@ func testAddAndGetUtxos(t *testing.T, repo domain.UtxoRepository) { require.NoError(t, err) require.Len(t, utxos, len(newUtxos)) - utxos, err = repo.GetAllUtxosForAccount(ctx, accountName) + utxos, err = repo.GetAllUtxosForAccount(ctx, accountName, nil) require.NoError(t, err) require.Len(t, utxos, len(newUtxos)) - utxos, err = repo.GetAllUtxosForAccount(ctx, wrongAccountName) + utxos, err = repo.GetAllUtxosForAccount(ctx, wrongAccountName, nil) require.NoError(t, err) require.Empty(t, utxos) @@ -82,11 +82,11 @@ func testAddAndGetUtxos(t *testing.T, repo domain.UtxoRepository) { require.NoError(t, err) require.Empty(t, utxos) - utxos, err = repo.GetSpendableUtxosForAccount(ctx, accountName, nil) + utxos, err = repo.GetSpendableUtxosForAccount(ctx, accountName) require.NoError(t, err) require.Empty(t, utxos) - utxos, err = repo.GetLockedUtxosForAccount(ctx, accountName, nil) + utxos, err = repo.GetLockedUtxosForAccount(ctx, accountName) require.NoError(t, err) require.Empty(t, utxos) @@ -140,7 +140,7 @@ func testConfirmUtxos(t *testing.T, repo domain.UtxoRepository) { require.NoError(t, err) require.Len(t, utxos, len(newUtxos)) - utxos, err = repo.GetSpendableUtxosForAccount(ctx, accountName, nil) + utxos, err = repo.GetSpendableUtxosForAccount(ctx, accountName) require.NoError(t, err) require.Len(t, utxos, len(newUtxos)) @@ -166,7 +166,7 @@ func testLockUtxos(t *testing.T, repo domain.UtxoRepository) { require.NoError(t, err) require.Zero(t, count) - utxos, err := repo.GetLockedUtxosForAccount(ctx, accountName, nil) + utxos, err := repo.GetLockedUtxosForAccount(ctx, accountName) require.NoError(t, err) require.Len(t, utxos, len(newUtxos)) @@ -174,7 +174,7 @@ func testLockUtxos(t *testing.T, repo domain.UtxoRepository) { require.NoError(t, err) require.Empty(t, utxos) - utxos, err = repo.GetSpendableUtxosForAccount(ctx, accountName, nil) + utxos, err = repo.GetSpendableUtxosForAccount(ctx, accountName) require.NoError(t, err) require.Empty(t, utxos) @@ -200,7 +200,7 @@ func testUnlockUtxos(t *testing.T, repo domain.UtxoRepository) { require.NoError(t, err) require.Zero(t, count) - utxos, err := repo.GetLockedUtxosForAccount(ctx, accountName, nil) + utxos, err := repo.GetLockedUtxosForAccount(ctx, accountName) require.NoError(t, err) require.Empty(t, utxos) @@ -208,7 +208,7 @@ func testUnlockUtxos(t *testing.T, repo domain.UtxoRepository) { require.NoError(t, err) require.Len(t, utxos, len(newUtxos)) - utxos, err = repo.GetSpendableUtxosForAccount(ctx, accountName, nil) + utxos, err = repo.GetSpendableUtxosForAccount(ctx, accountName) require.NoError(t, err) require.Len(t, utxos, len(newUtxos)) @@ -238,7 +238,7 @@ func testSpendUtxos(t *testing.T, repo domain.UtxoRepository) { require.NoError(t, err) require.Empty(t, utxos) - utxos, err = repo.GetSpendableUtxosForAccount(ctx, accountName, nil) + utxos, err = repo.GetSpendableUtxosForAccount(ctx, accountName) require.NoError(t, err) require.Empty(t, utxos) @@ -268,7 +268,7 @@ func testConfirmSpentUtxos(t *testing.T, repo domain.UtxoRepository) { require.NoError(t, err) require.Empty(t, utxos) - utxos, err = repo.GetSpendableUtxosForAccount(ctx, accountName, nil) + utxos, err = repo.GetSpendableUtxosForAccount(ctx, accountName) require.NoError(t, err) require.Empty(t, utxos) diff --git a/internal/interfaces/grpc/handler/account.go b/internal/interfaces/grpc/handler/account.go index a26f94d..06aa6d0 100644 --- a/internal/interfaces/grpc/handler/account.go +++ b/internal/interfaces/grpc/handler/account.go @@ -190,6 +190,7 @@ func (a *account) ListUtxos( } spendableUtxos := parseUtxos(utxosInfo.Spendable.Info()) lockedUtxos := parseUtxos(utxosInfo.Locked.Info()) + unconfirmedUtxos := parseUtxos(utxosInfo.Unconfirmed.Info()) return &pb.ListUtxosResponse{ SpendableUtxos: &pb.Utxos{ AccountName: name, @@ -199,6 +200,10 @@ func (a *account) ListUtxos( AccountName: name, Utxos: lockedUtxos, }, + UnconfirmedUtxos: &pb.Utxos{ + AccountName: name, + Utxos: unconfirmedUtxos, + }, }, nil } From 012489be00b44ee52390bcc527985072d7c744b8 Mon Sep 17 00:00:00 2001 From: altafan <18440657+altafan@users.noreply.github.com> Date: Thu, 29 Feb 2024 13:27:55 +0100 Subject: [PATCH 4/6] Fix --- .../infrastructure/storage/db/inmemory/utxo_repository.go | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/internal/infrastructure/storage/db/inmemory/utxo_repository.go b/internal/infrastructure/storage/db/inmemory/utxo_repository.go index d2f5e29..e159145 100644 --- a/internal/infrastructure/storage/db/inmemory/utxo_repository.go +++ b/internal/infrastructure/storage/db/inmemory/utxo_repository.go @@ -273,16 +273,12 @@ func (r *utxoRepository) getUtxosForAccount( filteredUtxos := make([]*domain.Utxo, 0, len(utxos)) for _, u := range utxos { - found := false for _, script := range scripts { if bytes.Equal(u.Script, script) { - found = true + filteredUtxos = append(filteredUtxos, u) break } } - if found { - filteredUtxos = append(filteredUtxos, u) - } } return filteredUtxos, nil } From 525fb74c8f4ed8cfa14e50d3922c3381f985b23a Mon Sep 17 00:00:00 2001 From: altafan <18440657+altafan@users.noreply.github.com> Date: Thu, 29 Feb 2024 14:31:37 +0100 Subject: [PATCH 5/6] Include unconfirmed utxos in spendable --- .../storage/db/badger/utxo_repository.go | 3 +- .../storage/db/inmemory/utxo_repository.go | 6 +-- .../storage/db/postgres/utxo_repository.go | 6 +-- .../storage/db/test/utxo_repository_test.go | 44 +++++++++++++++++-- 4 files changed, 47 insertions(+), 12 deletions(-) diff --git a/internal/infrastructure/storage/db/badger/utxo_repository.go b/internal/infrastructure/storage/db/badger/utxo_repository.go index a0d31a7..2b3c105 100644 --- a/internal/infrastructure/storage/db/badger/utxo_repository.go +++ b/internal/infrastructure/storage/db/badger/utxo_repository.go @@ -70,7 +70,7 @@ func (r *utxoRepository) GetSpendableUtxos( ctx context.Context, ) ([]*domain.Utxo, error) { query := badgerhold.Where("SpentStatus").Eq(domain.UtxoStatus{}). - And("ConfirmedStatus").Ne(domain.UtxoStatus{}).And("LockTimestamp").Eq(int64(0)) + And("LockTimestamp").Eq(int64(0)) return r.findUtxos(ctx, query) } @@ -105,7 +105,6 @@ func (r *utxoRepository) GetSpendableUtxosForAccount( ctx context.Context, accountName string, ) ([]*domain.Utxo, error) { query := badgerhold.Where("SpentStatus").Eq(domain.UtxoStatus{}). - And("ConfirmedStatus").Ne(domain.UtxoStatus{}). And("LockTimestamp").Eq(int64(0)).And("AccountName").Eq(accountName) return r.findUtxos(ctx, query) diff --git a/internal/infrastructure/storage/db/inmemory/utxo_repository.go b/internal/infrastructure/storage/db/inmemory/utxo_repository.go index e159145..04e2efd 100644 --- a/internal/infrastructure/storage/db/inmemory/utxo_repository.go +++ b/internal/infrastructure/storage/db/inmemory/utxo_repository.go @@ -229,7 +229,7 @@ func (r *utxoRepository) getUtxos(spendableOnly bool) []*domain.Utxo { utxos := make([]*domain.Utxo, 0, len(r.store.utxos)) for _, u := range r.store.utxos { if spendableOnly { - if !u.IsLocked() && u.IsConfirmed() && !u.IsSpent() { + if !u.IsLocked() && !u.IsSpent() { utxos = append(utxos, u) } continue @@ -252,14 +252,14 @@ func (r *utxoRepository) getUtxosForAccount( u := r.store.utxos[k.Hash()] if spendableOnly { - if !u.IsLocked() && u.IsConfirmed() && !u.IsSpent() { + if !u.IsLocked() && !u.IsSpent() { utxos = append(utxos, u) } continue } if lockedOnly { - if u.IsLocked() { + if u.IsLocked() && !u.IsSpent() { utxos = append(utxos, u) } continue diff --git a/internal/infrastructure/storage/db/postgres/utxo_repository.go b/internal/infrastructure/storage/db/postgres/utxo_repository.go index 31f3247..62d4271 100644 --- a/internal/infrastructure/storage/db/postgres/utxo_repository.go +++ b/internal/infrastructure/storage/db/postgres/utxo_repository.go @@ -230,7 +230,7 @@ func (u *utxoRepositoryPg) GetSpendableUtxos( } for _, v := range utxosByKey { - if !v.IsLocked() && v.IsConfirmed() && !v.IsSpent() { + if !v.IsLocked() && !v.IsSpent() { resp = append(resp, v) } } @@ -301,7 +301,7 @@ func (u *utxoRepositoryPg) GetSpendableUtxosForAccount( } for _, v := range utxosByKey { - if !v.IsLocked() && v.IsConfirmed() && !v.IsSpent() { + if !v.IsLocked() && !v.IsSpent() { resp = append(resp, v) } } @@ -333,7 +333,7 @@ func (u *utxoRepositoryPg) GetLockedUtxosForAccount( } for _, v := range utxosByKey { - if v.IsLocked() { + if v.IsLocked() && !v.IsSpent() { resp = append(resp, v) } } diff --git a/internal/infrastructure/storage/db/test/utxo_repository_test.go b/internal/infrastructure/storage/db/test/utxo_repository_test.go index 8db818c..3ef0e2b 100644 --- a/internal/infrastructure/storage/db/test/utxo_repository_test.go +++ b/internal/infrastructure/storage/db/test/utxo_repository_test.go @@ -80,11 +80,29 @@ func testAddAndGetUtxos(t *testing.T, repo domain.UtxoRepository) { utxos, err = repo.GetSpendableUtxos(ctx) require.NoError(t, err) - require.Empty(t, utxos) + confirmedUtxos, unconfirmedUtxos := make([]*domain.Utxo, 0), make([]*domain.Utxo, 0) + for _, u := range utxos { + if u.IsConfirmed() { + confirmedUtxos = append(confirmedUtxos, u) + continue + } + unconfirmedUtxos = append(unconfirmedUtxos, u) + } + require.Empty(t, confirmedUtxos) + require.Len(t, unconfirmedUtxos, len(newUtxos)) utxos, err = repo.GetSpendableUtxosForAccount(ctx, accountName) require.NoError(t, err) - require.Empty(t, utxos) + confirmedUtxos, unconfirmedUtxos = make([]*domain.Utxo, 0), make([]*domain.Utxo, 0) + for _, u := range utxos { + if u.IsConfirmed() { + confirmedUtxos = append(confirmedUtxos, u) + continue + } + unconfirmedUtxos = append(unconfirmedUtxos, u) + } + require.Empty(t, confirmedUtxos) + require.Len(t, unconfirmedUtxos, len(newUtxos)) utxos, err = repo.GetLockedUtxosForAccount(ctx, accountName) require.NoError(t, err) @@ -138,11 +156,29 @@ func testConfirmUtxos(t *testing.T, repo domain.UtxoRepository) { utxos, err := repo.GetSpendableUtxos(ctx) require.NoError(t, err) - require.Len(t, utxos, len(newUtxos)) + confirmedUtxos, unconfirmedUtxos := make([]*domain.Utxo, 0), make([]*domain.Utxo, 0) + for _, u := range utxos { + if u.IsConfirmed() { + confirmedUtxos = append(confirmedUtxos, u) + continue + } + unconfirmedUtxos = append(unconfirmedUtxos, u) + } + require.Empty(t, unconfirmedUtxos) + require.Len(t, confirmedUtxos, len(newUtxos)) utxos, err = repo.GetSpendableUtxosForAccount(ctx, accountName) require.NoError(t, err) - require.Len(t, utxos, len(newUtxos)) + confirmedUtxos, unconfirmedUtxos = make([]*domain.Utxo, 0), make([]*domain.Utxo, 0) + for _, u := range utxos { + if u.IsConfirmed() { + confirmedUtxos = append(confirmedUtxos, u) + continue + } + unconfirmedUtxos = append(unconfirmedUtxos, u) + } + require.Empty(t, unconfirmedUtxos) + require.Len(t, confirmedUtxos, len(newUtxos)) utxoBalance, err := repo.GetBalanceForAccount(ctx, accountName) require.NoError(t, err) From f2f02d2fc39d481e3418d0b989932f9041efc349 Mon Sep 17 00:00:00 2001 From: altafan <18440657+altafan@users.noreply.github.com> Date: Thu, 29 Feb 2024 14:45:58 +0100 Subject: [PATCH 6/6] Revert & Return unconf utxos in list of spendable --- .../protobuf/gen/go/ocean/v1/account.pb.go | 227 +++++++++--------- api-spec/protobuf/ocean/v1/account.proto | 2 - internal/core/application/account_service.go | 23 +- .../core/application/transaction_service.go | 6 +- internal/core/application/types.go | 5 +- internal/core/domain/utxo_repository.go | 11 +- .../storage/db/badger/utxo_repository.go | 44 +++- .../storage/db/inmemory/utxo_repository.go | 12 +- .../storage/db/postgres/utxo_repository.go | 39 +-- .../storage/db/test/utxo_repository_test.go | 22 +- internal/interfaces/grpc/handler/account.go | 5 - 11 files changed, 197 insertions(+), 199 deletions(-) diff --git a/api-spec/protobuf/gen/go/ocean/v1/account.pb.go b/api-spec/protobuf/gen/go/ocean/v1/account.pb.go index a900c59..dc81e7b 100644 --- a/api-spec/protobuf/gen/go/ocean/v1/account.pb.go +++ b/api-spec/protobuf/gen/go/ocean/v1/account.pb.go @@ -1011,8 +1011,6 @@ type ListUtxosResponse struct { SpendableUtxos *Utxos `protobuf:"bytes,1,opt,name=spendable_utxos,json=spendableUtxos,proto3" json:"spendable_utxos,omitempty"` // List of currently locked utxos. LockedUtxos *Utxos `protobuf:"bytes,2,opt,name=locked_utxos,json=lockedUtxos,proto3" json:"locked_utxos,omitempty"` - // List of unconfirmed utxos. - UnconfirmedUtxos *Utxos `protobuf:"bytes,3,opt,name=unconfirmed_utxos,json=unconfirmedUtxos,proto3" json:"unconfirmed_utxos,omitempty"` } func (x *ListUtxosResponse) Reset() { @@ -1061,13 +1059,6 @@ func (x *ListUtxosResponse) GetLockedUtxos() *Utxos { return nil } -func (x *ListUtxosResponse) GetUnconfirmedUtxos() *Utxos { - if x != nil { - return x.UnconfirmedUtxos - } - return nil -} - type DeleteAccountRequest struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache @@ -1257,7 +1248,7 @@ var file_ocean_v1_account_proto_rawDesc = []byte{ 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x61, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x1c, 0x0a, 0x09, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x65, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x09, 0x52, 0x09, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, - 0x65, 0x73, 0x22, 0xbf, 0x01, 0x0a, 0x11, 0x4c, 0x69, 0x73, 0x74, 0x55, 0x74, 0x78, 0x6f, 0x73, + 0x65, 0x73, 0x22, 0x81, 0x01, 0x0a, 0x11, 0x4c, 0x69, 0x73, 0x74, 0x55, 0x74, 0x78, 0x6f, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x38, 0x0a, 0x0f, 0x73, 0x70, 0x65, 0x6e, 0x64, 0x61, 0x62, 0x6c, 0x65, 0x5f, 0x75, 0x74, 0x78, 0x6f, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0f, 0x2e, 0x6f, 0x63, 0x65, 0x61, 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x55, 0x74, 0x78, @@ -1265,89 +1256,86 @@ var file_ocean_v1_account_proto_rawDesc = []byte{ 0x6f, 0x73, 0x12, 0x32, 0x0a, 0x0c, 0x6c, 0x6f, 0x63, 0x6b, 0x65, 0x64, 0x5f, 0x75, 0x74, 0x78, 0x6f, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0f, 0x2e, 0x6f, 0x63, 0x65, 0x61, 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x55, 0x74, 0x78, 0x6f, 0x73, 0x52, 0x0b, 0x6c, 0x6f, 0x63, 0x6b, 0x65, - 0x64, 0x55, 0x74, 0x78, 0x6f, 0x73, 0x12, 0x3c, 0x0a, 0x11, 0x75, 0x6e, 0x63, 0x6f, 0x6e, 0x66, - 0x69, 0x72, 0x6d, 0x65, 0x64, 0x5f, 0x75, 0x74, 0x78, 0x6f, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, - 0x0b, 0x32, 0x0f, 0x2e, 0x6f, 0x63, 0x65, 0x61, 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x55, 0x74, 0x78, - 0x6f, 0x73, 0x52, 0x10, 0x75, 0x6e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x72, 0x6d, 0x65, 0x64, 0x55, - 0x74, 0x78, 0x6f, 0x73, 0x22, 0x39, 0x0a, 0x14, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x41, 0x63, - 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x21, 0x0a, 0x0c, - 0x61, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x0b, 0x61, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x4e, 0x61, 0x6d, 0x65, 0x22, - 0x17, 0x0a, 0x15, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x41, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, - 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x32, 0xe4, 0x07, 0x0a, 0x0e, 0x41, 0x63, 0x63, - 0x6f, 0x75, 0x6e, 0x74, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x5f, 0x0a, 0x12, 0x43, + 0x64, 0x55, 0x74, 0x78, 0x6f, 0x73, 0x22, 0x39, 0x0a, 0x14, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, + 0x41, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x21, + 0x0a, 0x0c, 0x61, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x61, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x4e, 0x61, 0x6d, + 0x65, 0x22, 0x17, 0x0a, 0x15, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x41, 0x63, 0x63, 0x6f, 0x75, + 0x6e, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x32, 0xe4, 0x07, 0x0a, 0x0e, 0x41, + 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x5f, 0x0a, + 0x12, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x41, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x42, 0x49, + 0x50, 0x34, 0x34, 0x12, 0x23, 0x2e, 0x6f, 0x63, 0x65, 0x61, 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x41, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x42, 0x49, 0x50, 0x34, - 0x34, 0x12, 0x23, 0x2e, 0x6f, 0x63, 0x65, 0x61, 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x72, 0x65, - 0x61, 0x74, 0x65, 0x41, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x42, 0x49, 0x50, 0x34, 0x34, 0x52, - 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x24, 0x2e, 0x6f, 0x63, 0x65, 0x61, 0x6e, 0x2e, 0x76, - 0x31, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x41, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x42, - 0x49, 0x50, 0x34, 0x34, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x68, 0x0a, 0x15, - 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x41, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x4d, 0x75, 0x6c, - 0x74, 0x69, 0x53, 0x69, 0x67, 0x12, 0x26, 0x2e, 0x6f, 0x63, 0x65, 0x61, 0x6e, 0x2e, 0x76, 0x31, - 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x41, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x4d, 0x75, - 0x6c, 0x74, 0x69, 0x53, 0x69, 0x67, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x27, 0x2e, - 0x6f, 0x63, 0x65, 0x61, 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x41, - 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x4d, 0x75, 0x6c, 0x74, 0x69, 0x53, 0x69, 0x67, 0x52, 0x65, - 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x62, 0x0a, 0x13, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, - 0x41, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x43, 0x75, 0x73, 0x74, 0x6f, 0x6d, 0x12, 0x24, 0x2e, - 0x6f, 0x63, 0x65, 0x61, 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x41, - 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x43, 0x75, 0x73, 0x74, 0x6f, 0x6d, 0x52, 0x65, 0x71, 0x75, - 0x65, 0x73, 0x74, 0x1a, 0x25, 0x2e, 0x6f, 0x63, 0x65, 0x61, 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x43, - 0x72, 0x65, 0x61, 0x74, 0x65, 0x41, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x43, 0x75, 0x73, 0x74, - 0x6f, 0x6d, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x56, 0x0a, 0x0f, 0x53, 0x65, - 0x74, 0x41, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x4c, 0x61, 0x62, 0x65, 0x6c, 0x12, 0x20, 0x2e, - 0x6f, 0x63, 0x65, 0x61, 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x65, 0x74, 0x41, 0x63, 0x63, 0x6f, - 0x75, 0x6e, 0x74, 0x4c, 0x61, 0x62, 0x65, 0x6c, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, - 0x21, 0x2e, 0x6f, 0x63, 0x65, 0x61, 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x65, 0x74, 0x41, 0x63, - 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x4c, 0x61, 0x62, 0x65, 0x6c, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, - 0x73, 0x65, 0x12, 0x5f, 0x0a, 0x12, 0x53, 0x65, 0x74, 0x41, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, - 0x54, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x12, 0x23, 0x2e, 0x6f, 0x63, 0x65, 0x61, 0x6e, - 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x65, 0x74, 0x41, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x54, 0x65, - 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x24, 0x2e, - 0x6f, 0x63, 0x65, 0x61, 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x65, 0x74, 0x41, 0x63, 0x63, 0x6f, - 0x75, 0x6e, 0x74, 0x54, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, - 0x6e, 0x73, 0x65, 0x12, 0x56, 0x0a, 0x0f, 0x44, 0x65, 0x72, 0x69, 0x76, 0x65, 0x41, 0x64, 0x64, - 0x72, 0x65, 0x73, 0x73, 0x65, 0x73, 0x12, 0x20, 0x2e, 0x6f, 0x63, 0x65, 0x61, 0x6e, 0x2e, 0x76, - 0x31, 0x2e, 0x44, 0x65, 0x72, 0x69, 0x76, 0x65, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x65, - 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x21, 0x2e, 0x6f, 0x63, 0x65, 0x61, 0x6e, + 0x34, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x24, 0x2e, 0x6f, 0x63, 0x65, 0x61, 0x6e, + 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x41, 0x63, 0x63, 0x6f, 0x75, 0x6e, + 0x74, 0x42, 0x49, 0x50, 0x34, 0x34, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x68, + 0x0a, 0x15, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x41, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x4d, + 0x75, 0x6c, 0x74, 0x69, 0x53, 0x69, 0x67, 0x12, 0x26, 0x2e, 0x6f, 0x63, 0x65, 0x61, 0x6e, 0x2e, + 0x76, 0x31, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x41, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, + 0x4d, 0x75, 0x6c, 0x74, 0x69, 0x53, 0x69, 0x67, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, + 0x27, 0x2e, 0x6f, 0x63, 0x65, 0x61, 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, + 0x65, 0x41, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x4d, 0x75, 0x6c, 0x74, 0x69, 0x53, 0x69, 0x67, + 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x62, 0x0a, 0x13, 0x43, 0x72, 0x65, 0x61, + 0x74, 0x65, 0x41, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x43, 0x75, 0x73, 0x74, 0x6f, 0x6d, 0x12, + 0x24, 0x2e, 0x6f, 0x63, 0x65, 0x61, 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, + 0x65, 0x41, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x43, 0x75, 0x73, 0x74, 0x6f, 0x6d, 0x52, 0x65, + 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x25, 0x2e, 0x6f, 0x63, 0x65, 0x61, 0x6e, 0x2e, 0x76, 0x31, + 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x41, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x43, 0x75, + 0x73, 0x74, 0x6f, 0x6d, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x56, 0x0a, 0x0f, + 0x53, 0x65, 0x74, 0x41, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x4c, 0x61, 0x62, 0x65, 0x6c, 0x12, + 0x20, 0x2e, 0x6f, 0x63, 0x65, 0x61, 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x65, 0x74, 0x41, 0x63, + 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x4c, 0x61, 0x62, 0x65, 0x6c, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, + 0x74, 0x1a, 0x21, 0x2e, 0x6f, 0x63, 0x65, 0x61, 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x65, 0x74, + 0x41, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x4c, 0x61, 0x62, 0x65, 0x6c, 0x52, 0x65, 0x73, 0x70, + 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x5f, 0x0a, 0x12, 0x53, 0x65, 0x74, 0x41, 0x63, 0x63, 0x6f, 0x75, + 0x6e, 0x74, 0x54, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x12, 0x23, 0x2e, 0x6f, 0x63, 0x65, + 0x61, 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x65, 0x74, 0x41, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, + 0x54, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, + 0x24, 0x2e, 0x6f, 0x63, 0x65, 0x61, 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x65, 0x74, 0x41, 0x63, + 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x54, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x52, 0x65, 0x73, + 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x56, 0x0a, 0x0f, 0x44, 0x65, 0x72, 0x69, 0x76, 0x65, 0x41, + 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x65, 0x73, 0x12, 0x20, 0x2e, 0x6f, 0x63, 0x65, 0x61, 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x44, 0x65, 0x72, 0x69, 0x76, 0x65, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, - 0x73, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x68, 0x0a, 0x15, 0x44, - 0x65, 0x72, 0x69, 0x76, 0x65, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x41, 0x64, 0x64, 0x72, 0x65, - 0x73, 0x73, 0x65, 0x73, 0x12, 0x26, 0x2e, 0x6f, 0x63, 0x65, 0x61, 0x6e, 0x2e, 0x76, 0x31, 0x2e, - 0x44, 0x65, 0x72, 0x69, 0x76, 0x65, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x41, 0x64, 0x64, 0x72, - 0x65, 0x73, 0x73, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x27, 0x2e, 0x6f, - 0x63, 0x65, 0x61, 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x44, 0x65, 0x72, 0x69, 0x76, 0x65, 0x43, 0x68, - 0x61, 0x6e, 0x67, 0x65, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x65, 0x73, 0x52, 0x65, 0x73, - 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x50, 0x0a, 0x0d, 0x4c, 0x69, 0x73, 0x74, 0x41, 0x64, 0x64, - 0x72, 0x65, 0x73, 0x73, 0x65, 0x73, 0x12, 0x1e, 0x2e, 0x6f, 0x63, 0x65, 0x61, 0x6e, 0x2e, 0x76, - 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x65, 0x73, 0x52, - 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1f, 0x2e, 0x6f, 0x63, 0x65, 0x61, 0x6e, 0x2e, 0x76, - 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x65, 0x73, 0x52, - 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x3e, 0x0a, 0x07, 0x42, 0x61, 0x6c, 0x61, 0x6e, - 0x63, 0x65, 0x12, 0x18, 0x2e, 0x6f, 0x63, 0x65, 0x61, 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x42, 0x61, - 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x19, 0x2e, 0x6f, - 0x63, 0x65, 0x61, 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x42, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x52, - 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x44, 0x0a, 0x09, 0x4c, 0x69, 0x73, 0x74, 0x55, - 0x74, 0x78, 0x6f, 0x73, 0x12, 0x1a, 0x2e, 0x6f, 0x63, 0x65, 0x61, 0x6e, 0x2e, 0x76, 0x31, 0x2e, - 0x4c, 0x69, 0x73, 0x74, 0x55, 0x74, 0x78, 0x6f, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, - 0x1a, 0x1b, 0x2e, 0x6f, 0x63, 0x65, 0x61, 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, - 0x55, 0x74, 0x78, 0x6f, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x50, 0x0a, - 0x0d, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x41, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x1e, - 0x2e, 0x6f, 0x63, 0x65, 0x61, 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, - 0x41, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1f, - 0x2e, 0x6f, 0x63, 0x65, 0x61, 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, - 0x41, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x42, - 0xa5, 0x01, 0x0a, 0x0c, 0x63, 0x6f, 0x6d, 0x2e, 0x6f, 0x63, 0x65, 0x61, 0x6e, 0x2e, 0x76, 0x31, - 0x42, 0x0c, 0x41, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01, - 0x5a, 0x46, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x76, 0x75, 0x6c, - 0x70, 0x65, 0x6d, 0x76, 0x65, 0x6e, 0x74, 0x75, 0x72, 0x65, 0x73, 0x2f, 0x6f, 0x63, 0x65, 0x61, - 0x6e, 0x2f, 0x61, 0x70, 0x69, 0x2d, 0x73, 0x70, 0x65, 0x63, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, - 0x62, 0x75, 0x66, 0x2f, 0x67, 0x65, 0x6e, 0x2f, 0x6f, 0x63, 0x65, 0x61, 0x6e, 0x2f, 0x76, 0x31, - 0x3b, 0x6f, 0x63, 0x65, 0x61, 0x6e, 0x76, 0x31, 0xa2, 0x02, 0x03, 0x4f, 0x58, 0x58, 0xaa, 0x02, - 0x08, 0x4f, 0x63, 0x65, 0x61, 0x6e, 0x2e, 0x56, 0x31, 0xca, 0x02, 0x08, 0x4f, 0x63, 0x65, 0x61, - 0x6e, 0x5c, 0x56, 0x31, 0xe2, 0x02, 0x14, 0x4f, 0x63, 0x65, 0x61, 0x6e, 0x5c, 0x56, 0x31, 0x5c, - 0x47, 0x50, 0x42, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0xea, 0x02, 0x09, 0x4f, 0x63, - 0x65, 0x61, 0x6e, 0x3a, 0x3a, 0x56, 0x31, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x73, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x21, 0x2e, 0x6f, 0x63, 0x65, + 0x61, 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x44, 0x65, 0x72, 0x69, 0x76, 0x65, 0x41, 0x64, 0x64, 0x72, + 0x65, 0x73, 0x73, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x68, 0x0a, + 0x15, 0x44, 0x65, 0x72, 0x69, 0x76, 0x65, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x41, 0x64, 0x64, + 0x72, 0x65, 0x73, 0x73, 0x65, 0x73, 0x12, 0x26, 0x2e, 0x6f, 0x63, 0x65, 0x61, 0x6e, 0x2e, 0x76, + 0x31, 0x2e, 0x44, 0x65, 0x72, 0x69, 0x76, 0x65, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x41, 0x64, + 0x64, 0x72, 0x65, 0x73, 0x73, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x27, + 0x2e, 0x6f, 0x63, 0x65, 0x61, 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x44, 0x65, 0x72, 0x69, 0x76, 0x65, + 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x65, 0x73, 0x52, + 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x50, 0x0a, 0x0d, 0x4c, 0x69, 0x73, 0x74, 0x41, + 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x65, 0x73, 0x12, 0x1e, 0x2e, 0x6f, 0x63, 0x65, 0x61, 0x6e, + 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x65, + 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1f, 0x2e, 0x6f, 0x63, 0x65, 0x61, 0x6e, + 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x65, + 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x3e, 0x0a, 0x07, 0x42, 0x61, 0x6c, + 0x61, 0x6e, 0x63, 0x65, 0x12, 0x18, 0x2e, 0x6f, 0x63, 0x65, 0x61, 0x6e, 0x2e, 0x76, 0x31, 0x2e, + 0x42, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x19, + 0x2e, 0x6f, 0x63, 0x65, 0x61, 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x42, 0x61, 0x6c, 0x61, 0x6e, 0x63, + 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x44, 0x0a, 0x09, 0x4c, 0x69, 0x73, + 0x74, 0x55, 0x74, 0x78, 0x6f, 0x73, 0x12, 0x1a, 0x2e, 0x6f, 0x63, 0x65, 0x61, 0x6e, 0x2e, 0x76, + 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x55, 0x74, 0x78, 0x6f, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, + 0x73, 0x74, 0x1a, 0x1b, 0x2e, 0x6f, 0x63, 0x65, 0x61, 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, + 0x73, 0x74, 0x55, 0x74, 0x78, 0x6f, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, + 0x50, 0x0a, 0x0d, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x41, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, + 0x12, 0x1e, 0x2e, 0x6f, 0x63, 0x65, 0x61, 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x44, 0x65, 0x6c, 0x65, + 0x74, 0x65, 0x41, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, + 0x1a, 0x1f, 0x2e, 0x6f, 0x63, 0x65, 0x61, 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x44, 0x65, 0x6c, 0x65, + 0x74, 0x65, 0x41, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, + 0x65, 0x42, 0xa5, 0x01, 0x0a, 0x0c, 0x63, 0x6f, 0x6d, 0x2e, 0x6f, 0x63, 0x65, 0x61, 0x6e, 0x2e, + 0x76, 0x31, 0x42, 0x0c, 0x41, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x50, 0x72, 0x6f, 0x74, 0x6f, + 0x50, 0x01, 0x5a, 0x46, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x76, + 0x75, 0x6c, 0x70, 0x65, 0x6d, 0x76, 0x65, 0x6e, 0x74, 0x75, 0x72, 0x65, 0x73, 0x2f, 0x6f, 0x63, + 0x65, 0x61, 0x6e, 0x2f, 0x61, 0x70, 0x69, 0x2d, 0x73, 0x70, 0x65, 0x63, 0x2f, 0x70, 0x72, 0x6f, + 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2f, 0x67, 0x65, 0x6e, 0x2f, 0x6f, 0x63, 0x65, 0x61, 0x6e, 0x2f, + 0x76, 0x31, 0x3b, 0x6f, 0x63, 0x65, 0x61, 0x6e, 0x76, 0x31, 0xa2, 0x02, 0x03, 0x4f, 0x58, 0x58, + 0xaa, 0x02, 0x08, 0x4f, 0x63, 0x65, 0x61, 0x6e, 0x2e, 0x56, 0x31, 0xca, 0x02, 0x08, 0x4f, 0x63, + 0x65, 0x61, 0x6e, 0x5c, 0x56, 0x31, 0xe2, 0x02, 0x14, 0x4f, 0x63, 0x65, 0x61, 0x6e, 0x5c, 0x56, + 0x31, 0x5c, 0x47, 0x50, 0x42, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0xea, 0x02, 0x09, + 0x4f, 0x63, 0x65, 0x61, 0x6e, 0x3a, 0x3a, 0x56, 0x31, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, + 0x33, } var ( @@ -1401,35 +1389,34 @@ var file_ocean_v1_account_proto_depIdxs = []int32{ 22, // 5: ocean.v1.BalanceResponse.balance:type_name -> ocean.v1.BalanceResponse.BalanceEntry 25, // 6: ocean.v1.ListUtxosResponse.spendable_utxos:type_name -> ocean.v1.Utxos 25, // 7: ocean.v1.ListUtxosResponse.locked_utxos:type_name -> ocean.v1.Utxos - 25, // 8: ocean.v1.ListUtxosResponse.unconfirmed_utxos:type_name -> ocean.v1.Utxos - 26, // 9: ocean.v1.BalanceResponse.BalanceEntry.value:type_name -> ocean.v1.BalanceInfo - 0, // 10: ocean.v1.AccountService.CreateAccountBIP44:input_type -> ocean.v1.CreateAccountBIP44Request - 2, // 11: ocean.v1.AccountService.CreateAccountMultiSig:input_type -> ocean.v1.CreateAccountMultiSigRequest - 4, // 12: ocean.v1.AccountService.CreateAccountCustom:input_type -> ocean.v1.CreateAccountCustomRequest - 6, // 13: ocean.v1.AccountService.SetAccountLabel:input_type -> ocean.v1.SetAccountLabelRequest - 8, // 14: ocean.v1.AccountService.SetAccountTemplate:input_type -> ocean.v1.SetAccountTemplateRequest - 10, // 15: ocean.v1.AccountService.DeriveAddresses:input_type -> ocean.v1.DeriveAddressesRequest - 12, // 16: ocean.v1.AccountService.DeriveChangeAddresses:input_type -> ocean.v1.DeriveChangeAddressesRequest - 14, // 17: ocean.v1.AccountService.ListAddresses:input_type -> ocean.v1.ListAddressesRequest - 16, // 18: ocean.v1.AccountService.Balance:input_type -> ocean.v1.BalanceRequest - 18, // 19: ocean.v1.AccountService.ListUtxos:input_type -> ocean.v1.ListUtxosRequest - 20, // 20: ocean.v1.AccountService.DeleteAccount:input_type -> ocean.v1.DeleteAccountRequest - 1, // 21: ocean.v1.AccountService.CreateAccountBIP44:output_type -> ocean.v1.CreateAccountBIP44Response - 3, // 22: ocean.v1.AccountService.CreateAccountMultiSig:output_type -> ocean.v1.CreateAccountMultiSigResponse - 5, // 23: ocean.v1.AccountService.CreateAccountCustom:output_type -> ocean.v1.CreateAccountCustomResponse - 7, // 24: ocean.v1.AccountService.SetAccountLabel:output_type -> ocean.v1.SetAccountLabelResponse - 9, // 25: ocean.v1.AccountService.SetAccountTemplate:output_type -> ocean.v1.SetAccountTemplateResponse - 11, // 26: ocean.v1.AccountService.DeriveAddresses:output_type -> ocean.v1.DeriveAddressesResponse - 13, // 27: ocean.v1.AccountService.DeriveChangeAddresses:output_type -> ocean.v1.DeriveChangeAddressesResponse - 15, // 28: ocean.v1.AccountService.ListAddresses:output_type -> ocean.v1.ListAddressesResponse - 17, // 29: ocean.v1.AccountService.Balance:output_type -> ocean.v1.BalanceResponse - 19, // 30: ocean.v1.AccountService.ListUtxos:output_type -> ocean.v1.ListUtxosResponse - 21, // 31: ocean.v1.AccountService.DeleteAccount:output_type -> ocean.v1.DeleteAccountResponse - 21, // [21:32] is the sub-list for method output_type - 10, // [10:21] is the sub-list for method input_type - 10, // [10:10] is the sub-list for extension type_name - 10, // [10:10] is the sub-list for extension extendee - 0, // [0:10] is the sub-list for field type_name + 26, // 8: ocean.v1.BalanceResponse.BalanceEntry.value:type_name -> ocean.v1.BalanceInfo + 0, // 9: ocean.v1.AccountService.CreateAccountBIP44:input_type -> ocean.v1.CreateAccountBIP44Request + 2, // 10: ocean.v1.AccountService.CreateAccountMultiSig:input_type -> ocean.v1.CreateAccountMultiSigRequest + 4, // 11: ocean.v1.AccountService.CreateAccountCustom:input_type -> ocean.v1.CreateAccountCustomRequest + 6, // 12: ocean.v1.AccountService.SetAccountLabel:input_type -> ocean.v1.SetAccountLabelRequest + 8, // 13: ocean.v1.AccountService.SetAccountTemplate:input_type -> ocean.v1.SetAccountTemplateRequest + 10, // 14: ocean.v1.AccountService.DeriveAddresses:input_type -> ocean.v1.DeriveAddressesRequest + 12, // 15: ocean.v1.AccountService.DeriveChangeAddresses:input_type -> ocean.v1.DeriveChangeAddressesRequest + 14, // 16: ocean.v1.AccountService.ListAddresses:input_type -> ocean.v1.ListAddressesRequest + 16, // 17: ocean.v1.AccountService.Balance:input_type -> ocean.v1.BalanceRequest + 18, // 18: ocean.v1.AccountService.ListUtxos:input_type -> ocean.v1.ListUtxosRequest + 20, // 19: ocean.v1.AccountService.DeleteAccount:input_type -> ocean.v1.DeleteAccountRequest + 1, // 20: ocean.v1.AccountService.CreateAccountBIP44:output_type -> ocean.v1.CreateAccountBIP44Response + 3, // 21: ocean.v1.AccountService.CreateAccountMultiSig:output_type -> ocean.v1.CreateAccountMultiSigResponse + 5, // 22: ocean.v1.AccountService.CreateAccountCustom:output_type -> ocean.v1.CreateAccountCustomResponse + 7, // 23: ocean.v1.AccountService.SetAccountLabel:output_type -> ocean.v1.SetAccountLabelResponse + 9, // 24: ocean.v1.AccountService.SetAccountTemplate:output_type -> ocean.v1.SetAccountTemplateResponse + 11, // 25: ocean.v1.AccountService.DeriveAddresses:output_type -> ocean.v1.DeriveAddressesResponse + 13, // 26: ocean.v1.AccountService.DeriveChangeAddresses:output_type -> ocean.v1.DeriveChangeAddressesResponse + 15, // 27: ocean.v1.AccountService.ListAddresses:output_type -> ocean.v1.ListAddressesResponse + 17, // 28: ocean.v1.AccountService.Balance:output_type -> ocean.v1.BalanceResponse + 19, // 29: ocean.v1.AccountService.ListUtxos:output_type -> ocean.v1.ListUtxosResponse + 21, // 30: ocean.v1.AccountService.DeleteAccount:output_type -> ocean.v1.DeleteAccountResponse + 20, // [20:31] is the sub-list for method output_type + 9, // [9:20] is the sub-list for method input_type + 9, // [9:9] is the sub-list for extension type_name + 9, // [9:9] is the sub-list for extension extendee + 0, // [0:9] is the sub-list for field type_name } func init() { file_ocean_v1_account_proto_init() } diff --git a/api-spec/protobuf/ocean/v1/account.proto b/api-spec/protobuf/ocean/v1/account.proto index da6193f..47b5d99 100644 --- a/api-spec/protobuf/ocean/v1/account.proto +++ b/api-spec/protobuf/ocean/v1/account.proto @@ -150,8 +150,6 @@ message ListUtxosResponse{ Utxos spendable_utxos = 1; // List of currently locked utxos. Utxos locked_utxos = 2; - // List of unconfirmed utxos. - Utxos unconfirmed_utxos = 3; } message DeleteAccountRequest{ diff --git a/internal/core/application/account_service.go b/internal/core/application/account_service.go index 854e34a..f063a72 100644 --- a/internal/core/application/account_service.go +++ b/internal/core/application/account_service.go @@ -172,30 +172,21 @@ func (as *AccountService) ListUtxosForAccount( return nil, err } - utxos, err := as.repoManager.UtxoRepository().GetAllUtxosForAccount( + spendableUtxos, err := as.repoManager.UtxoRepository().GetSpendableUtxosForAccount( ctx, account.Namespace, scripts, ) if err != nil { return nil, err } - spendableUtxos := make([]*domain.Utxo, 0, len(utxos)) - unconfirmedUtxos := make([]*domain.Utxo, 0, len(utxos)) - lockedUtxos := make([]*domain.Utxo, 0, len(utxos)) - - for _, u := range utxos { - if u.IsLocked() { - lockedUtxos = append(lockedUtxos, u) - } else { - if u.IsConfirmed() { - spendableUtxos = append(spendableUtxos, u) - } else { - unconfirmedUtxos = append(unconfirmedUtxos, u) - } - } + lockedUtxos, err := as.repoManager.UtxoRepository().GetLockedUtxosForAccount( + ctx, account.Namespace, scripts, + ) + if err != nil { + return nil, err } - return &UtxoInfo{spendableUtxos, lockedUtxos, unconfirmedUtxos}, nil + return &UtxoInfo{spendableUtxos, lockedUtxos}, nil } func (as *AccountService) DeleteAccount( diff --git a/internal/core/application/transaction_service.go b/internal/core/application/transaction_service.go index 12ce586..9359241 100644 --- a/internal/core/application/transaction_service.go +++ b/internal/core/application/transaction_service.go @@ -105,7 +105,7 @@ func (ts *TransactionService) SelectUtxos( } utxos, err := ts.repoManager.UtxoRepository().GetSpendableUtxosForAccount( - ctx, account.Namespace, + ctx, account.Namespace, nil, ) if err != nil { return nil, 0, -1, err @@ -396,7 +396,7 @@ func (ts *TransactionService) Transfer( } utxos, err := utxoRepo.GetSpendableUtxosForAccount( - ctx, account.Namespace, + ctx, account.Namespace, nil, ) if err != nil { return "", err @@ -778,7 +778,7 @@ func (ts *TransactionService) scheduleUtxoUnlocker() { for accountName := range w.Accounts { utxos, _ := utxoRepo.GetLockedUtxosForAccount( - ctx, accountName, + ctx, accountName, nil, ) if len(utxos) > 0 { utxosToUnlock := make([]domain.UtxoKey, 0, len(utxos)) diff --git a/internal/core/application/types.go b/internal/core/application/types.go index e02a49a..5727b30 100644 --- a/internal/core/application/types.go +++ b/internal/core/application/types.go @@ -55,9 +55,8 @@ type BuildInfo struct { } type UtxoInfo struct { - Spendable Utxos - Locked Utxos - Unconfirmed Utxos + Spendable Utxos + Locked Utxos } type TransactionInfo domain.Transaction diff --git a/internal/core/domain/utxo_repository.go b/internal/core/domain/utxo_repository.go index 5e9c1e3..bb43a28 100644 --- a/internal/core/domain/utxo_repository.go +++ b/internal/core/domain/utxo_repository.go @@ -51,14 +51,15 @@ type UtxoRepository interface { // GetSpendableUtxos returns all unlocked utxo UTXOs. GetSpendableUtxos(ctx context.Context) ([]*Utxo, error) // GetAllUtxosForAccount returns the list of all utxos for the given - // account. Can be filtered by output scripts. - GetAllUtxosForAccount(ctx context.Context, account string, scripts [][]byte) ([]*Utxo, error) + // account. + GetAllUtxosForAccount(ctx context.Context, account string) ([]*Utxo, error) // GetSpendableUtxosForAccount returns the list of spendable utxos for the // given account. The list incldues only confirmed and unlocked utxos. - GetSpendableUtxosForAccount(ctx context.Context, account string) ([]*Utxo, error) + // Can be filtered by output scripts. + GetSpendableUtxosForAccount(ctx context.Context, account string, scripts [][]byte) ([]*Utxo, error) // GetLockedUtxosForAccount returns the list of all currently locked utxos - // for the given account. - GetLockedUtxosForAccount(ctx context.Context, account string) ([]*Utxo, error) + // for the given account. Can be filtered by output scripts. + GetLockedUtxosForAccount(ctx context.Context, account string, scripts [][]byte) ([]*Utxo, error) // GetBalanceForAccount returns the confirmed, unconfirmed and locked // balances per each asset for the given account. GetBalanceForAccount(ctx context.Context, account string) (map[string]*Balance, error) diff --git a/internal/infrastructure/storage/db/badger/utxo_repository.go b/internal/infrastructure/storage/db/badger/utxo_repository.go index 2b3c105..0995d52 100644 --- a/internal/infrastructure/storage/db/badger/utxo_repository.go +++ b/internal/infrastructure/storage/db/badger/utxo_repository.go @@ -76,10 +76,19 @@ func (r *utxoRepository) GetSpendableUtxos( } func (r *utxoRepository) GetAllUtxosForAccount( - ctx context.Context, accountName string, scripts [][]byte, + ctx context.Context, accountName string, ) ([]*domain.Utxo, error) { query := badgerhold.Where("AccountName").Eq(accountName) + return r.findUtxos(ctx, query) +} + +func (r *utxoRepository) GetSpendableUtxosForAccount( + ctx context.Context, accountName string, scripts [][]byte, +) ([]*domain.Utxo, error) { + query := badgerhold.Where("SpentStatus").Eq(domain.UtxoStatus{}). + And("LockTimestamp").Eq(int64(0)).And("AccountName").Eq(accountName) + utxos, err := r.findUtxos(ctx, query) if err != nil { return nil, err @@ -101,28 +110,37 @@ func (r *utxoRepository) GetAllUtxosForAccount( return filteredUtxos, nil } -func (r *utxoRepository) GetSpendableUtxosForAccount( - ctx context.Context, accountName string, -) ([]*domain.Utxo, error) { - query := badgerhold.Where("SpentStatus").Eq(domain.UtxoStatus{}). - And("LockTimestamp").Eq(int64(0)).And("AccountName").Eq(accountName) - - return r.findUtxos(ctx, query) -} - func (r *utxoRepository) GetLockedUtxosForAccount( - ctx context.Context, accountName string, + ctx context.Context, accountName string, scripts [][]byte, ) ([]*domain.Utxo, error) { query := badgerhold.Where("SpentStatus").Eq(domain.UtxoStatus{}). And("LockTimestamp").Gt(int64(0)).And("AccountName").Eq(accountName) - return r.findUtxos(ctx, query) + utxos, err := r.findUtxos(ctx, query) + if err != nil { + return nil, err + } + + if len(scripts) <= 0 { + return utxos, nil + } + + filteredUtxos := make([]*domain.Utxo, 0, len(utxos)) + for _, u := range utxos { + for _, script := range scripts { + if bytes.Equal(u.Script, script) { + filteredUtxos = append(filteredUtxos, u) + break + } + } + } + return filteredUtxos, nil } func (r *utxoRepository) GetBalanceForAccount( ctx context.Context, accountName string, ) (map[string]*domain.Balance, error) { - utxos, err := r.GetAllUtxosForAccount(ctx, accountName, nil) + utxos, err := r.GetAllUtxosForAccount(ctx, accountName) if err != nil { return nil, err } diff --git a/internal/infrastructure/storage/db/inmemory/utxo_repository.go b/internal/infrastructure/storage/db/inmemory/utxo_repository.go index 04e2efd..0f5b593 100644 --- a/internal/infrastructure/storage/db/inmemory/utxo_repository.go +++ b/internal/infrastructure/storage/db/inmemory/utxo_repository.go @@ -80,30 +80,30 @@ func (r *utxoRepository) GetSpendableUtxos(_ context.Context) ([]*domain.Utxo, e } func (r *utxoRepository) GetAllUtxosForAccount( - _ context.Context, account string, scripts [][]byte, + _ context.Context, account string, ) ([]*domain.Utxo, error) { r.store.lock.RLock() defer r.store.lock.RUnlock() - return r.getUtxosForAccount(account, false, false, scripts) + return r.getUtxosForAccount(account, false, false, nil) } func (r *utxoRepository) GetSpendableUtxosForAccount( - _ context.Context, account string, + _ context.Context, account string, scripts [][]byte, ) ([]*domain.Utxo, error) { r.store.lock.RLock() defer r.store.lock.RUnlock() - return r.getUtxosForAccount(account, true, false, nil) + return r.getUtxosForAccount(account, true, false, scripts) } func (r *utxoRepository) GetLockedUtxosForAccount( - _ context.Context, account string, + _ context.Context, account string, scripts [][]byte, ) ([]*domain.Utxo, error) { r.store.lock.RLock() defer r.store.lock.RUnlock() - return r.getUtxosForAccount(account, false, true, nil) + return r.getUtxosForAccount(account, false, true, scripts) } func (r *utxoRepository) GetBalanceForAccount( diff --git a/internal/infrastructure/storage/db/postgres/utxo_repository.go b/internal/infrastructure/storage/db/postgres/utxo_repository.go index 62d4271..97f0c1f 100644 --- a/internal/infrastructure/storage/db/postgres/utxo_repository.go +++ b/internal/infrastructure/storage/db/postgres/utxo_repository.go @@ -239,7 +239,7 @@ func (u *utxoRepositoryPg) GetSpendableUtxos( } func (u *utxoRepositoryPg) GetAllUtxosForAccount( - ctx context.Context, account string, scripts [][]byte, + ctx context.Context, account string, ) ([]*domain.Utxo, error) { resp := make([]*domain.Utxo, 0) utxos, err := u.querier.GetUtxosForAccount(ctx, account) @@ -262,23 +262,14 @@ func (u *utxoRepositoryPg) GetAllUtxosForAccount( } for _, v := range utxosByKey { - found := len(scripts) <= 0 - for _, script := range scripts { - if bytes.Equal(v.Script, script) { - found = true - break - } - } - if found { - resp = append(resp, v) - } + resp = append(resp, v) } return resp, nil } func (u *utxoRepositoryPg) GetSpendableUtxosForAccount( - ctx context.Context, account string, + ctx context.Context, account string, scripts [][]byte, ) ([]*domain.Utxo, error) { resp := make([]*domain.Utxo, 0) utxos, err := u.querier.GetUtxosForAccount(ctx, account) @@ -302,7 +293,16 @@ func (u *utxoRepositoryPg) GetSpendableUtxosForAccount( for _, v := range utxosByKey { if !v.IsLocked() && !v.IsSpent() { - resp = append(resp, v) + found := len(scripts) <= 0 + for _, script := range scripts { + if bytes.Equal(v.Script, script) { + found = true + break + } + } + if found { + resp = append(resp, v) + } } } @@ -310,7 +310,7 @@ func (u *utxoRepositoryPg) GetSpendableUtxosForAccount( } func (u *utxoRepositoryPg) GetLockedUtxosForAccount( - ctx context.Context, account string, + ctx context.Context, account string, scripts [][]byte, ) ([]*domain.Utxo, error) { resp := make([]*domain.Utxo, 0) utxos, err := u.querier.GetUtxosForAccount(ctx, account) @@ -334,7 +334,16 @@ func (u *utxoRepositoryPg) GetLockedUtxosForAccount( for _, v := range utxosByKey { if v.IsLocked() && !v.IsSpent() { - resp = append(resp, v) + found := len(scripts) <= 0 + for _, script := range scripts { + if bytes.Equal(v.Script, script) { + found = true + break + } + } + if found { + resp = append(resp, v) + } } } diff --git a/internal/infrastructure/storage/db/test/utxo_repository_test.go b/internal/infrastructure/storage/db/test/utxo_repository_test.go index 3ef0e2b..b066a42 100644 --- a/internal/infrastructure/storage/db/test/utxo_repository_test.go +++ b/internal/infrastructure/storage/db/test/utxo_repository_test.go @@ -70,11 +70,11 @@ func testAddAndGetUtxos(t *testing.T, repo domain.UtxoRepository) { require.NoError(t, err) require.Len(t, utxos, len(newUtxos)) - utxos, err = repo.GetAllUtxosForAccount(ctx, accountName, nil) + utxos, err = repo.GetAllUtxosForAccount(ctx, accountName) require.NoError(t, err) require.Len(t, utxos, len(newUtxos)) - utxos, err = repo.GetAllUtxosForAccount(ctx, wrongAccountName, nil) + utxos, err = repo.GetAllUtxosForAccount(ctx, wrongAccountName) require.NoError(t, err) require.Empty(t, utxos) @@ -91,7 +91,7 @@ func testAddAndGetUtxos(t *testing.T, repo domain.UtxoRepository) { require.Empty(t, confirmedUtxos) require.Len(t, unconfirmedUtxos, len(newUtxos)) - utxos, err = repo.GetSpendableUtxosForAccount(ctx, accountName) + utxos, err = repo.GetSpendableUtxosForAccount(ctx, accountName, nil) require.NoError(t, err) confirmedUtxos, unconfirmedUtxos = make([]*domain.Utxo, 0), make([]*domain.Utxo, 0) for _, u := range utxos { @@ -104,7 +104,7 @@ func testAddAndGetUtxos(t *testing.T, repo domain.UtxoRepository) { require.Empty(t, confirmedUtxos) require.Len(t, unconfirmedUtxos, len(newUtxos)) - utxos, err = repo.GetLockedUtxosForAccount(ctx, accountName) + utxos, err = repo.GetLockedUtxosForAccount(ctx, accountName, nil) require.NoError(t, err) require.Empty(t, utxos) @@ -167,7 +167,7 @@ func testConfirmUtxos(t *testing.T, repo domain.UtxoRepository) { require.Empty(t, unconfirmedUtxos) require.Len(t, confirmedUtxos, len(newUtxos)) - utxos, err = repo.GetSpendableUtxosForAccount(ctx, accountName) + utxos, err = repo.GetSpendableUtxosForAccount(ctx, accountName, nil) require.NoError(t, err) confirmedUtxos, unconfirmedUtxos = make([]*domain.Utxo, 0), make([]*domain.Utxo, 0) for _, u := range utxos { @@ -202,7 +202,7 @@ func testLockUtxos(t *testing.T, repo domain.UtxoRepository) { require.NoError(t, err) require.Zero(t, count) - utxos, err := repo.GetLockedUtxosForAccount(ctx, accountName) + utxos, err := repo.GetLockedUtxosForAccount(ctx, accountName, nil) require.NoError(t, err) require.Len(t, utxos, len(newUtxos)) @@ -210,7 +210,7 @@ func testLockUtxos(t *testing.T, repo domain.UtxoRepository) { require.NoError(t, err) require.Empty(t, utxos) - utxos, err = repo.GetSpendableUtxosForAccount(ctx, accountName) + utxos, err = repo.GetSpendableUtxosForAccount(ctx, accountName, nil) require.NoError(t, err) require.Empty(t, utxos) @@ -236,7 +236,7 @@ func testUnlockUtxos(t *testing.T, repo domain.UtxoRepository) { require.NoError(t, err) require.Zero(t, count) - utxos, err := repo.GetLockedUtxosForAccount(ctx, accountName) + utxos, err := repo.GetLockedUtxosForAccount(ctx, accountName, nil) require.NoError(t, err) require.Empty(t, utxos) @@ -244,7 +244,7 @@ func testUnlockUtxos(t *testing.T, repo domain.UtxoRepository) { require.NoError(t, err) require.Len(t, utxos, len(newUtxos)) - utxos, err = repo.GetSpendableUtxosForAccount(ctx, accountName) + utxos, err = repo.GetSpendableUtxosForAccount(ctx, accountName, nil) require.NoError(t, err) require.Len(t, utxos, len(newUtxos)) @@ -274,7 +274,7 @@ func testSpendUtxos(t *testing.T, repo domain.UtxoRepository) { require.NoError(t, err) require.Empty(t, utxos) - utxos, err = repo.GetSpendableUtxosForAccount(ctx, accountName) + utxos, err = repo.GetSpendableUtxosForAccount(ctx, accountName, nil) require.NoError(t, err) require.Empty(t, utxos) @@ -304,7 +304,7 @@ func testConfirmSpentUtxos(t *testing.T, repo domain.UtxoRepository) { require.NoError(t, err) require.Empty(t, utxos) - utxos, err = repo.GetSpendableUtxosForAccount(ctx, accountName) + utxos, err = repo.GetSpendableUtxosForAccount(ctx, accountName, nil) require.NoError(t, err) require.Empty(t, utxos) diff --git a/internal/interfaces/grpc/handler/account.go b/internal/interfaces/grpc/handler/account.go index 06aa6d0..a26f94d 100644 --- a/internal/interfaces/grpc/handler/account.go +++ b/internal/interfaces/grpc/handler/account.go @@ -190,7 +190,6 @@ func (a *account) ListUtxos( } spendableUtxos := parseUtxos(utxosInfo.Spendable.Info()) lockedUtxos := parseUtxos(utxosInfo.Locked.Info()) - unconfirmedUtxos := parseUtxos(utxosInfo.Unconfirmed.Info()) return &pb.ListUtxosResponse{ SpendableUtxos: &pb.Utxos{ AccountName: name, @@ -200,10 +199,6 @@ func (a *account) ListUtxos( AccountName: name, Utxos: lockedUtxos, }, - UnconfirmedUtxos: &pb.Utxos{ - AccountName: name, - Utxos: unconfirmedUtxos, - }, }, nil }