Skip to content

Commit

Permalink
Mf/add association txn types (deso-protocol#420)
Browse files Browse the repository at this point in the history
* Add associations txn type.

* Add put and delete badger operations for associations.

* Split into CREATE and DELETE txn types.

* Add metadata validations.

* Add connect create associations logic.

* Add connect delete association txns.

* Add disconnect logic.

* Add db adapter.

* Add badger getter queries.

* Add flush logic.

* Add postgres associations data types.

* Add postgres flush operations.

* Fix tabs.

* Add postgres getter queries.

* Add blockchain.go create txn funcs.

* Add association tx index structs.

* Add byte encoders.

* Dont error if dont find association in pg queries.

* Populate association tx index metadata.

* Add funcs to decode associations from bytes.

* Add create user association validation tests.

* Add delete user association validation tests.

* Refactor + consolidate association test helpers.

* Add happy path test for creating + deleting user association.

* Add post association tests.

* Get tests working on postgres.

* Add query funcs to find associations by attributes.

* Add postgres api queries.

* Add badger query for associations.

* Test wildcard user association matching.

* Add post association wildcard query helpers.

* Add post association query api tests.

* Make AssociationType case-insensitive.

* Fix failing CI test.

* Run tests twice. Once flushing. Once all in mempool.

* Fix failing CI.

* Retrigger CI.

* Add first failed test query.

* Improve mempool association querying test coverage.

* Improve test coverage moar.

* Improve test coverage moar moar.

* Touch-ups.

* Move back inline comment to fix gofmt.

* Run associations postgres tests in CI.

* Fail retrieving associations if no query params are set.

* Add AssociationTypePrefix and AssociationValuePrefix.

* Return nil in get association by ID if association was deleted.

* Dont include deleted associations in get by attributes query.

* Rename indices.

* Add AppUserPKID field.

* Add tests for app user pkid querying.

* Store ExtraData on AssociationEntries.

* Rename AppUserPKID to AppPKID.

* Add function to count matching association entries.

* Fix gofmt issue.

* Add tests for counting user associations.

* Add count post associations tests.

* Return new and deleted utxo association entries from helper.

* Fix go fmt.

* Add more association info to tx index.

* Address some PR feedback.

* Switch association type/value from strings to byte slices.

* Fix failing postgres tests.

* Move comparison of association types into helper func.

* Add association type postgres indices.

* Address some PR review feedback.

* Add makefile helper to go-fmt code.

* Add association encoder migrations.

* Mf/add advanced querying for associations (deso-protocol#430)

* Add advanced querying for associations.

* Add tests for limit, offset, order user association queries.

* Fix go-fmt issues.

* Add tests for limit, order, offset queries for post associations.

* Fix sort descending querying.

* Dont limit, offset, order count queries.

* Add generic set struct.

* Convert Limit from uint64 to int.

* Use sets instead of maps when possible.

* Address some PR review comments.

* Pass sets as pointers.

* Address some of PR review feedback.

* Fix gofmt issue.

* Rename utxo association variables.

* Address some PR review feedback.

* Better error messages for invalid query params.

* Simplify advanced query for associations by filtering out ALL associationIds when going to the db (deso-protocol#432)

* Simplify advanced query for associations by filtering out ALL associationIds when going to the db

* Validate LastSeenAssociationID exists. (deso-protocol#433)

Co-authored-by: Matt Foley <[email protected]>

Co-authored-by: Lazy Nina <[email protected]>

* Mf/add associations derived key spending limits (deso-protocol#435)

* Add association derived key spending limits.

* Add validation for derived key spending limit during txn connect.

* Fix failing test.

* Start adding test for associations spending limits.

* Update tests.

* Fix go-fmt.

* Simplify use of utxo view in association derived key test.

* Dont reuse utxo view.

* Add more tests.

* Set spending limit count properly.

* Add spending limit operation type ANY.

* Add more block height guards.

* Fix failing test with new encoding pattern.

* add range apply as faster way to iterate over elements in set (deso-protocol#434)

* Add advanced querying for associations.

* Add tests for limit, offset, order user association queries.

* Fix go-fmt issues.

* Add tests for limit, order, offset queries for post associations.

* Fix sort descending querying.

* Dont limit, offset, order count queries.

* Add generic set struct.

* Convert Limit from uint64 to int.

* Use sets instead of maps when possible.

* Address some PR review comments.

* Pass sets as pointers.

* Address some of PR review feedback.

* Fix gofmt issue.

* Rename utxo association variables.

* Address some PR review feedback.

* Better error messages for invalid query params.

* Simplify advanced query for associations by filtering out ALL associationIds when going to the db

* Validate LastSeenAssociationID exists. (deso-protocol#433)

* add range apply as faster way to iterate over elements in set

* fix gofmt errors

* get rid of ToOrderedSlice so we can make the hash set more space efficient

* run gofmt

* add return to inner func in DBGetPostAssociationsByAttributes

* add RangeMap function

* don't use pointers in set

* rename to ForEach and Map

* Query postgres with values instead of pointers.

* Fix go-fmt.

* remove map function from set

Co-authored-by: mattfoley8 <[email protected]>
Co-authored-by: Matt Foley <[email protected]>
Co-authored-by: Lazy Nina <>

* Dont pull deleted associations from the db. (deso-protocol#438)

* Dont pull deleted associations from the db.

* Remove whitespace.

* Update comment.

* Update comments more.

* Ln/add map set func (deso-protocol#439)

* Add map set function

* add map set function

* add error test for map set function

* fix typo

Co-authored-by: Lazy Nina <>

* Dont pass ExtraData for delete association txns.

* Revert "Dont pass ExtraData for delete association txns."

This reverts commit 9dfbf3b.

* validate association type and value does not contain null terminator (deso-protocol#443)

* Validate Association types and values do not contain null terminator:

* add test cases

* Refactor validation of app public key

* add function to check for existence of public key + pkid

* Diamondhands/associations review (deso-protocol#442)

* Improve snapshot and hypersync comments (deso-protocol#440)

* Improve snapshot and hypersync comments

* piotr's two cents

Co-authored-by: Piotr Nojszewski <[email protected]>

* Add associations txn type.

* Add put and delete badger operations for associations.

* Split into CREATE and DELETE txn types.

* Add metadata validations.

* Add connect create associations logic.

* Add connect delete association txns.

* Add disconnect logic.

* Add db adapter.

* Add badger getter queries.

* Add flush logic.

* Add postgres associations data types.

* Add postgres flush operations.

* Fix tabs.

* Add postgres getter queries.

* Add blockchain.go create txn funcs.

* Add association tx index structs.

* Add byte encoders.

* Dont error if dont find association in pg queries.

* Populate association tx index metadata.

* Add funcs to decode associations from bytes.

* Add create user association validation tests.

* Add delete user association validation tests.

* Refactor + consolidate association test helpers.

* Add happy path test for creating + deleting user association.

* Add post association tests.

* Get tests working on postgres.

* Add query funcs to find associations by attributes.

* Add postgres api queries.

* Add badger query for associations.

* Test wildcard user association matching.

* Add post association wildcard query helpers.

* Add post association query api tests.

* Make AssociationType case-insensitive.

* Fix failing CI test.

* Run tests twice. Once flushing. Once all in mempool.

* Fix failing CI.

* Add first failed test query.

* Improve mempool association querying test coverage.

* Improve test coverage moar.

* Improve test coverage moar moar.

* Touch-ups.

* Move back inline comment to fix gofmt.

* Run associations postgres tests in CI.

* Fail retrieving associations if no query params are set.

* Add AssociationTypePrefix and AssociationValuePrefix.

* Return nil in get association by ID if association was deleted.

* Dont include deleted associations in get by attributes query.

* Rename indices.

* Add AppUserPKID field.

* Add tests for app user pkid querying.

* Store ExtraData on AssociationEntries.

* Rename AppUserPKID to AppPKID.

* Add function to count matching association entries.

* Fix gofmt issue.

* Add tests for counting user associations.

* Add count post associations tests.

* Return new and deleted utxo association entries from helper.

* Fix go fmt.

* Add more association info to tx index.

* Address some PR feedback.

* Switch association type/value from strings to byte slices.

* Fix failing postgres tests.

* Move comparison of association types into helper func.

* Add association type postgres indices.

* Address some PR review feedback.

* Add makefile helper to go-fmt code.

* Add association encoder migrations.

* Mf/add advanced querying for associations (deso-protocol#430)

* Add advanced querying for associations.

* Add tests for limit, offset, order user association queries.

* Fix go-fmt issues.

* Add tests for limit, order, offset queries for post associations.

* Fix sort descending querying.

* Dont limit, offset, order count queries.

* Add generic set struct.

* Convert Limit from uint64 to int.

* Use sets instead of maps when possible.

* Address some PR review comments.

* Pass sets as pointers.

* Address some of PR review feedback.

* Fix gofmt issue.

* Rename utxo association variables.

* Address some PR review feedback.

* Better error messages for invalid query params.

* Simplify advanced query for associations by filtering out ALL associationIds when going to the db (deso-protocol#432)

* Simplify advanced query for associations by filtering out ALL associationIds when going to the db

* Validate LastSeenAssociationID exists. (deso-protocol#433)

Co-authored-by: Matt Foley <[email protected]>

Co-authored-by: Lazy Nina <[email protected]>

* Mf/add associations derived key spending limits (deso-protocol#435)

* Add association derived key spending limits.

* Add validation for derived key spending limit during txn connect.

* Fix failing test.

* Start adding test for associations spending limits.

* Update tests.

* Fix go-fmt.

* Simplify use of utxo view in association derived key test.

* Dont reuse utxo view.

* Add more tests.

* Set spending limit count properly.

* Add spending limit operation type ANY.

* Add more block height guards.

* Fix failing test with new encoding pattern.

* add range apply as faster way to iterate over elements in set (deso-protocol#434)

* Add advanced querying for associations.

* Add tests for limit, offset, order user association queries.

* Fix go-fmt issues.

* Add tests for limit, order, offset queries for post associations.

* Fix sort descending querying.

* Dont limit, offset, order count queries.

* Add generic set struct.

* Convert Limit from uint64 to int.

* Use sets instead of maps when possible.

* Address some PR review comments.

* Pass sets as pointers.

* Address some of PR review feedback.

* Fix gofmt issue.

* Rename utxo association variables.

* Address some PR review feedback.

* Better error messages for invalid query params.

* Simplify advanced query for associations by filtering out ALL associationIds when going to the db

* Validate LastSeenAssociationID exists. (deso-protocol#433)

* add range apply as faster way to iterate over elements in set

* fix gofmt errors

* get rid of ToOrderedSlice so we can make the hash set more space efficient

* run gofmt

* add return to inner func in DBGetPostAssociationsByAttributes

* add RangeMap function

* don't use pointers in set

* rename to ForEach and Map

* Query postgres with values instead of pointers.

* Fix go-fmt.

* remove map function from set

Co-authored-by: mattfoley8 <[email protected]>
Co-authored-by: Matt Foley <[email protected]>
Co-authored-by: Lazy Nina <>

* Dont pull deleted associations from the db. (deso-protocol#438)

* Dont pull deleted associations from the db.

* Remove whitespace.

* Update comment.

* Update comments more.

* Ln/add map set func (deso-protocol#439)

* Add map set function

* add map set function

* add error test for map set function

* fix typo

Co-authored-by: Lazy Nina <>

* Dont pass ExtraData for delete association txns.

* Revert "Dont pass ExtraData for delete association txns."

This reverts commit 9dfbf3b.

* Minor touchups

* gofmt

* add comments on db prefixes to specify value types

* gofmt

Co-authored-by: Piotr Nojszewski <[email protected]>
Co-authored-by: mattfoley8 <[email protected]>
Co-authored-by: Matt Foley <[email protected]>
Co-authored-by: Lazy Nina <[email protected]>
Co-authored-by: Lazy Nina <>

Co-authored-by: Lazy Nina <[email protected]>
Co-authored-by: diamondhands0 <[email protected]>
Co-authored-by: Piotr Nojszewski <[email protected]>
  • Loading branch information
4 people authored Jan 6, 2023
1 parent 70e9022 commit a80dec8
Show file tree
Hide file tree
Showing 22 changed files with 7,369 additions and 56 deletions.
4 changes: 3 additions & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,9 @@ jobs:
run: go run scripts/migrate.go migrate

- name: Run go test
run: go test -run TestDAOCoinLimitOrder -v ./lib
run: >-
go test -run TestAssociations -v ./lib &&
go test -run TestDAOCoinLimitOrder -v ./lib
- name: Rollback migrations
run: go run scripts/migrate.go rollback
3 changes: 3 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
go-fmt:
@gofmt -s -w .

postgres-start:
@docker-compose --file docker-compose.test.yml up --detach
@sleep 3
Expand Down
174 changes: 174 additions & 0 deletions lib/block_view.go
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,10 @@ type UtxoView struct {
// DAO coin limit order entry mapping.
DAOCoinLimitOrderMapKeyToDAOCoinLimitOrderEntry map[DAOCoinLimitOrderMapKey]*DAOCoinLimitOrderEntry

// Association mappings
AssociationMapKeyToUserAssociationEntry map[AssociationMapKey]*UserAssociationEntry
AssociationMapKeyToPostAssociationEntry map[AssociationMapKey]*PostAssociationEntry

// The hash of the tip the view is currently referencing. Mainly used
// for error-checking when doing a bulk operation on the view.
TipHash *BlockHash
Expand Down Expand Up @@ -159,6 +163,10 @@ func (bav *UtxoView) _ResetViewMappingsAfterFlush() {

// DAO Coin Limit Order Entries
bav.DAOCoinLimitOrderMapKeyToDAOCoinLimitOrderEntry = make(map[DAOCoinLimitOrderMapKey]*DAOCoinLimitOrderEntry)

// Association entries
bav.AssociationMapKeyToUserAssociationEntry = make(map[AssociationMapKey]*UserAssociationEntry)
bav.AssociationMapKeyToPostAssociationEntry = make(map[AssociationMapKey]*PostAssociationEntry)
}

func (bav *UtxoView) CopyUtxoView() (*UtxoView, error) {
Expand Down Expand Up @@ -353,6 +361,18 @@ func (bav *UtxoView) CopyUtxoView() (*UtxoView, error) {
newEntry := *entry
newView.DAOCoinLimitOrderMapKeyToDAOCoinLimitOrderEntry[entryKey] = &newEntry
}

// Copy the Association entries
newView.AssociationMapKeyToUserAssociationEntry = make(map[AssociationMapKey]*UserAssociationEntry, len(bav.AssociationMapKeyToUserAssociationEntry))
for entryKey, entry := range bav.AssociationMapKeyToUserAssociationEntry {
newEntry := *entry
newView.AssociationMapKeyToUserAssociationEntry[entryKey] = &newEntry
}
newView.AssociationMapKeyToPostAssociationEntry = make(map[AssociationMapKey]*PostAssociationEntry, len(bav.AssociationMapKeyToPostAssociationEntry))
for entryKey, entry := range bav.AssociationMapKeyToPostAssociationEntry {
newEntry := *entry
newView.AssociationMapKeyToPostAssociationEntry[entryKey] = &newEntry
}
return newView, nil
}

Expand Down Expand Up @@ -1004,6 +1024,22 @@ func (bav *UtxoView) DisconnectTransaction(currentTxn *MsgDeSoTxn, txnHash *Bloc
return bav._disconnectAuthorizeDerivedKey(
OperationTypeAuthorizeDerivedKey, currentTxn, txnHash, utxoOpsForTxn, blockHeight)

} else if currentTxn.TxnMeta.GetTxnType() == TxnTypeCreateUserAssociation {
return bav._disconnectCreateUserAssociation(
OperationTypeCreateUserAssociation, currentTxn, txnHash, utxoOpsForTxn, blockHeight)

} else if currentTxn.TxnMeta.GetTxnType() == TxnTypeDeleteUserAssociation {
return bav._disconnectDeleteUserAssociation(
OperationTypeDeleteUserAssociation, currentTxn, txnHash, utxoOpsForTxn, blockHeight)

} else if currentTxn.TxnMeta.GetTxnType() == TxnTypeCreatePostAssociation {
return bav._disconnectCreatePostAssociation(
OperationTypeCreatePostAssociation, currentTxn, txnHash, utxoOpsForTxn, blockHeight)

} else if currentTxn.TxnMeta.GetTxnType() == TxnTypeDeletePostAssociation {
return bav._disconnectDeletePostAssociation(
OperationTypeDeletePostAssociation, currentTxn, txnHash, utxoOpsForTxn, blockHeight)

}

return fmt.Errorf("DisconnectBlock: Unimplemented txn type %v", currentTxn.TxnMeta.GetTxnType().String())
Expand Down Expand Up @@ -1716,6 +1752,64 @@ func (bav *UtxoView) _checkDerivedKeySpendingLimit(
derivedKeyEntry, txnMeta.NFTPostHash, txnMeta.SerialNumber, BurnNFTOperation); err != nil {
return utxoOpsForTxn, err
}
case TxnTypeCreateUserAssociation:
txnMeta := txn.TxnMeta.(*CreateUserAssociationMetadata)
if derivedKeyEntry, err = bav._checkAssociationLimitAndUpdateDerivedKey(
derivedKeyEntry,
AssociationClassUser,
txnMeta.AssociationType,
txnMeta.AppPublicKey,
AssociationOperationCreate,
); err != nil {
return utxoOpsForTxn, errors.Wrapf(err, "_checkDerivedKeySpendingLimit: ")
}
case TxnTypeDeleteUserAssociation:
txnMeta := txn.TxnMeta.(*DeleteUserAssociationMetadata)
associationEntry, err := bav.GetUserAssociationByID(txnMeta.AssociationID)
if err != nil {
return utxoOpsForTxn, errors.Wrapf(err, "_checkDerivedKeySpendingLimit: ")
}
if associationEntry == nil {
return utxoOpsForTxn, errors.New("_checkDerivedKeySpendingLimit: association to delete not found")
}
if derivedKeyEntry, err = bav._checkAssociationLimitAndUpdateDerivedKey(
derivedKeyEntry,
AssociationClassUser,
associationEntry.AssociationType,
NewPublicKey(bav.GetPublicKeyForPKID(associationEntry.AppPKID)),
AssociationOperationDelete,
); err != nil {
return utxoOpsForTxn, errors.Wrapf(err, "_checkDerivedKeySpendingLimit: ")
}
case TxnTypeCreatePostAssociation:
txnMeta := txn.TxnMeta.(*CreateUserAssociationMetadata)
if derivedKeyEntry, err = bav._checkAssociationLimitAndUpdateDerivedKey(
derivedKeyEntry,
AssociationClassPost,
txnMeta.AssociationType,
txnMeta.AppPublicKey,
AssociationOperationCreate,
); err != nil {
return utxoOpsForTxn, errors.Wrapf(err, "_checkDerivedKeySpendingLimit: ")
}
case TxnTypeDeletePostAssociation:
txnMeta := txn.TxnMeta.(*DeletePostAssociationMetadata)
associationEntry, err := bav.GetPostAssociationByID(txnMeta.AssociationID)
if err != nil {
return utxoOpsForTxn, errors.Wrapf(err, "_checkDerivedKeySpendingLimit: ")
}
if associationEntry == nil {
return utxoOpsForTxn, errors.New("_checkDerivedKeySpendingLimit: association to delete not found")
}
if derivedKeyEntry, err = bav._checkAssociationLimitAndUpdateDerivedKey(
derivedKeyEntry,
AssociationClassPost,
associationEntry.AssociationType,
NewPublicKey(bav.GetPublicKeyForPKID(associationEntry.AppPKID)),
AssociationOperationDelete,
); err != nil {
return utxoOpsForTxn, errors.Wrapf(err, "_checkDerivedKeySpendingLimit: ")
}
default:
// If we get here, it means we're dealing with a txn that doesn't have any special
// granular limits to deal with. This means we just check whether we have
Expand Down Expand Up @@ -2026,6 +2120,74 @@ func (bav *UtxoView) _checkDAOCoinLimitOrderLimitAndUpdateDerivedKeyEntry(
"_checkDAOCoinLimitOrderLimitAndUpdateDerivedKeyEntr: DAO Coin limit order not authorized: ")
}

func (bav *UtxoView) _checkAssociationLimitAndUpdateDerivedKey(
derivedKeyEntry DerivedKeyEntry,
associationClass AssociationClass,
associationType []byte,
appPublicKey *PublicKey,
operation AssociationOperation,
) (DerivedKeyEntry, error) {
// Convert AppPublicKey to AppPKID
appPKID := bav._associationAppPublicKeyToPKID(appPublicKey)
// Construct AssociationLimitKey.
var associationLimitKey AssociationLimitKey
// Check for applicable spending limit matching:
// - Scoped AppScopeType else any AppScopeType
// - Scoped AssociationType else any AssociationType
// - Scoped OperationType else any OperationType
for _, spendingLimitScopeType := range []AssociationAppScopeType{AssociationAppScopeTypeScoped, AssociationAppScopeTypeAny} {
spendingLimitAppPKID := *appPKID
if spendingLimitScopeType == AssociationAppScopeTypeAny {
spendingLimitAppPKID = ZeroPKID
}
for _, spendingLimitAssociationType := range [][]byte{associationType, []byte("")} {
for _, spendingLimitOperationType := range []AssociationOperation{operation, AssociationOperationAny} {
associationLimitKey = MakeAssociationLimitKey(
associationClass,
spendingLimitAssociationType,
spendingLimitAppPKID,
spendingLimitScopeType,
spendingLimitOperationType,
)
updatedDerivedKeyEntry, err := _checkAssociationLimitAndUpdateDerivedKey(derivedKeyEntry, associationLimitKey)
if err == nil {
return updatedDerivedKeyEntry, nil
}
}
}
}
// If we get to this point, then no authorized spending limits
// were found and the association is not authorized.
return derivedKeyEntry, errors.New("_checkAssociationLimitAndUpdateDerivedKey: association not authorized for derived key")
}

func _checkAssociationLimitAndUpdateDerivedKey(
derivedKeyEntry DerivedKeyEntry, associationLimitKey AssociationLimitKey,
) (DerivedKeyEntry, error) {
errMsg := errors.New("_checkAssociationLimitAndUpdateDerivedKey: association not authorized for derived key")
// If derived key spending limit is missing, return unauthorized.
if derivedKeyEntry.TransactionSpendingLimitTracker == nil ||
derivedKeyEntry.TransactionSpendingLimitTracker.AssociationLimitMap == nil {
return derivedKeyEntry, errMsg
}
// Check if the key is present in the AssociationLimitMap.
associationLimit, associationLimitExists :=
derivedKeyEntry.TransactionSpendingLimitTracker.AssociationLimitMap[associationLimitKey]
// If the key doesn't exist or the value is <= 0, return unauthorized.
if !associationLimitExists || associationLimit <= 0 {
return derivedKeyEntry, errMsg
}
// If this is the last operation allowed for this key, we delete the key from the map.
if associationLimit == 1 {
delete(derivedKeyEntry.TransactionSpendingLimitTracker.AssociationLimitMap, associationLimitKey)
} else {
// Otherwise, we decrement the number of operations remaining for this key.
derivedKeyEntry.TransactionSpendingLimitTracker.AssociationLimitMap[associationLimitKey]--
}
// Happy path: we found the key and decremented the remaining operations.
return derivedKeyEntry, nil
}

func (bav *UtxoView) _connectUpdateGlobalParams(
txn *MsgDeSoTxn, txHash *BlockHash, blockHeight uint32, verifySignatures bool) (
_totalInput uint64, _totalOutput uint64, _utxoOps []*UtxoOperation, _err error) {
Expand Down Expand Up @@ -2380,6 +2542,18 @@ func (bav *UtxoView) _connectTransaction(txn *MsgDeSoTxn, txHash *BlockHash,
bav._connectAuthorizeDerivedKey(
txn, txHash, blockHeight, verifySignatures)

} else if txn.TxnMeta.GetTxnType() == TxnTypeCreateUserAssociation {
totalInput, totalOutput, utxoOpsForTxn, err = bav._connectCreateUserAssociation(txn, txHash, blockHeight, verifySignatures)

} else if txn.TxnMeta.GetTxnType() == TxnTypeDeleteUserAssociation {
totalInput, totalOutput, utxoOpsForTxn, err = bav._connectDeleteUserAssociation(txn, txHash, blockHeight, verifySignatures)

} else if txn.TxnMeta.GetTxnType() == TxnTypeCreatePostAssociation {
totalInput, totalOutput, utxoOpsForTxn, err = bav._connectCreatePostAssociation(txn, txHash, blockHeight, verifySignatures)

} else if txn.TxnMeta.GetTxnType() == TxnTypeDeletePostAssociation {
totalInput, totalOutput, utxoOpsForTxn, err = bav._connectDeletePostAssociation(txn, txHash, blockHeight, verifySignatures)

} else {
err = fmt.Errorf("ConnectTransaction: Unimplemented txn type %v", txn.TxnMeta.GetTxnType().String())
}
Expand Down
Loading

0 comments on commit a80dec8

Please sign in to comment.