Skip to content

Commit

Permalink
Return unconfirmed utxos
Browse files Browse the repository at this point in the history
  • Loading branch information
altafan committed Feb 28, 2024
1 parent 5656729 commit b2a0895
Show file tree
Hide file tree
Showing 11 changed files with 200 additions and 198 deletions.
227 changes: 120 additions & 107 deletions api-spec/protobuf/gen/go/ocean/v1/account.pb.go

Large diffs are not rendered by default.

2 changes: 2 additions & 0 deletions api-spec/protobuf/ocean/v1/account.proto
Original file line number Diff line number Diff line change
Expand Up @@ -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{
Expand Down
23 changes: 16 additions & 7 deletions internal/core/application/account_service.go
Original file line number Diff line number Diff line change
Expand Up @@ -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(
Expand Down
6 changes: 3 additions & 3 deletions internal/core/application/transaction_service.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -396,7 +396,7 @@ func (ts *TransactionService) Transfer(
}

utxos, err := utxoRepo.GetSpendableUtxosForAccount(
ctx, account.Namespace, nil,
ctx, account.Namespace,
)
if err != nil {
return "", err
Expand Down Expand Up @@ -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))
Expand Down
5 changes: 3 additions & 2 deletions internal/core/application/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -55,8 +55,9 @@ type BuildInfo struct {
}

type UtxoInfo struct {
Spendable Utxos
Locked Utxos
Spendable Utxos
Locked Utxos
Unconfirmed Utxos
}

type TransactionInfo domain.Transaction
Expand Down
11 changes: 5 additions & 6 deletions internal/core/domain/utxo_repository.go
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
46 changes: 14 additions & 32 deletions internal/infrastructure/storage/db/badger/utxo_repository.go
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand All @@ -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
}
Expand Down
12 changes: 6 additions & 6 deletions internal/infrastructure/storage/db/inmemory/utxo_repository.go
Original file line number Diff line number Diff line change
Expand Up @@ -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(
Expand Down
39 changes: 15 additions & 24 deletions internal/infrastructure/storage/db/postgres/utxo_repository.go
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand All @@ -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)
Expand All @@ -293,24 +302,15 @@ 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)
}
}

return resp, nil
}

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)
Expand All @@ -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)
}
}

Expand Down
22 changes: 11 additions & 11 deletions internal/infrastructure/storage/db/test/utxo_repository_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -70,23 +70,23 @@ 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)

utxos, err = repo.GetSpendableUtxos(ctx)
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)

Expand Down Expand Up @@ -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))

Expand All @@ -166,15 +166,15 @@ 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))

utxos, err = repo.GetSpendableUtxos(ctx)
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)

Expand All @@ -200,15 +200,15 @@ 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)

utxos, err = repo.GetSpendableUtxos(ctx)
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))

Expand Down Expand Up @@ -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)

Expand Down Expand Up @@ -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)

Expand Down
Loading

0 comments on commit b2a0895

Please sign in to comment.