Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 8 additions & 8 deletions docs/swagger/swagger.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -4661,13 +4661,13 @@ paths:
type:
enum:
- blockchain_batch_pin
- blockchain_invoke
- publicstorage_batch_broadcast
- dataexchange_batch_send
- dataexchange_blob_send
- token_create_pool
- token_announce_pool
- token_activate_pool
- token_transfer
- contract_invoke
type: string
updated: {}
type: object
Expand Down Expand Up @@ -5423,13 +5423,13 @@ paths:
type:
enum:
- blockchain_batch_pin
- blockchain_invoke
- publicstorage_batch_broadcast
- dataexchange_batch_send
- dataexchange_blob_send
- token_create_pool
- token_announce_pool
- token_activate_pool
- token_transfer
- contract_invoke
type: string
updated: {}
type: object
Expand Down Expand Up @@ -5489,13 +5489,13 @@ paths:
type:
enum:
- blockchain_batch_pin
- blockchain_invoke
- publicstorage_batch_broadcast
- dataexchange_batch_send
- dataexchange_blob_send
- token_create_pool
- token_announce_pool
- token_activate_pool
- token_transfer
- contract_invoke
type: string
updated: {}
type: object
Expand Down Expand Up @@ -8063,13 +8063,13 @@ paths:
type:
enum:
- blockchain_batch_pin
- blockchain_invoke
- publicstorage_batch_broadcast
- dataexchange_batch_send
- dataexchange_blob_send
- token_create_pool
- token_announce_pool
- token_activate_pool
- token_transfer
- contract_invoke
type: string
updated: {}
type: object
Expand Down
27 changes: 25 additions & 2 deletions internal/assets/token_pool.go
Original file line number Diff line number Diff line change
Expand Up @@ -90,15 +90,38 @@ func (am *assetManager) createTokenPoolInternal(ctx context.Context, pool *fftyp
return nil, err
}

return pool, plugin.CreateTokenPool(ctx, op.ID, pool)
if complete, err := plugin.CreateTokenPool(ctx, op.ID, pool); err != nil {
return nil, err
} else if complete {
update := database.OperationQueryFactory.NewUpdate(ctx).Set("status", fftypes.OpStatusSucceeded)
return pool, am.database.UpdateOperation(ctx, op.ID, update)
}
return pool, nil
}

func (am *assetManager) ActivateTokenPool(ctx context.Context, pool *fftypes.TokenPool, event *fftypes.BlockchainEvent) error {
plugin, err := am.selectTokenPlugin(ctx, pool.Connector)
if err != nil {
return err
}
return plugin.ActivateTokenPool(ctx, nil, pool, event)

op := fftypes.NewOperation(
plugin,
pool.Namespace,
pool.TX.ID,
"",
fftypes.OpTypeTokenActivatePool)
if err := am.database.InsertOperation(ctx, op); err != nil {
return err
}

if complete, err := plugin.ActivateTokenPool(ctx, op.ID, pool, event); err != nil {
return err
} else if complete {
update := database.OperationQueryFactory.NewUpdate(ctx).Set("status", fftypes.OpStatusSucceeded)
return am.database.UpdateOperation(ctx, op.ID, update)
}
return nil
}

func (am *assetManager) GetTokenPools(ctx context.Context, ns string, filter database.AndFilter) ([]*fftypes.TokenPool, *database.FilterResult, error) {
Expand Down
111 changes: 104 additions & 7 deletions internal/assets/token_pool_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ func TestCreateTokenPoolUnknownConnectorSuccess(t *testing.T) {
mth := am.txHelper.(*txcommonmocks.Helper)
mim.On("GetLocalOrganization", context.Background()).Return(&fftypes.Organization{Identity: "0x12345"}, nil)
mdm.On("VerifyNamespaceExists", context.Background(), "ns1").Return(nil)
mti.On("CreateTokenPool", context.Background(), mock.Anything, mock.Anything, mock.Anything).Return(nil)
mti.On("CreateTokenPool", context.Background(), mock.Anything, mock.Anything, mock.Anything).Return(false, nil)
mth.On("SubmitNewTransaction", context.Background(), "ns1", fftypes.TransactionTypeTokenPool).Return(fftypes.NewUUID(), nil)
mdi.On("InsertOperation", context.Background(), mock.Anything).Return(nil)

Expand Down Expand Up @@ -121,7 +121,7 @@ func TestCreateTokenPoolMissingNamespace(t *testing.T) {
mth := am.txHelper.(*txcommonmocks.Helper)
mim.On("GetLocalOrganization", context.Background()).Return(&fftypes.Organization{Identity: "0x12345"}, nil)
mdm.On("VerifyNamespaceExists", context.Background(), "ns1").Return(nil).Times(2)
mti.On("CreateTokenPool", context.Background(), mock.Anything, mock.Anything).Return(nil).Times(1)
mti.On("CreateTokenPool", context.Background(), mock.Anything, mock.Anything).Return(false, nil).Times(1)
mth.On("SubmitNewTransaction", context.Background(), "ns1", fftypes.TransactionTypeTokenPool).Return(fftypes.NewUUID(), nil)
mdi.On("InsertOperation", context.Background(), mock.Anything).Return(nil).Times(1)
msa.On("WaitForTokenPool", context.Background(), "ns1", mock.Anything, mock.Anything).
Expand Down Expand Up @@ -209,7 +209,7 @@ func TestCreateTokenPoolFail(t *testing.T) {
mdm.On("VerifyNamespaceExists", context.Background(), "ns1").Return(nil)
mth.On("SubmitNewTransaction", context.Background(), "ns1", fftypes.TransactionTypeTokenPool).Return(fftypes.NewUUID(), nil)
mdi.On("InsertOperation", context.Background(), mock.Anything).Return(nil)
mti.On("CreateTokenPool", context.Background(), mock.Anything, mock.Anything, mock.Anything).Return(fmt.Errorf("pop"))
mti.On("CreateTokenPool", context.Background(), mock.Anything, mock.Anything, mock.Anything).Return(false, fmt.Errorf("pop"))

_, err := am.CreateTokenPool(context.Background(), "ns1", pool, false)
assert.Regexp(t, "pop", err)
Expand All @@ -235,7 +235,7 @@ func TestCreateTokenPoolTransactionFail(t *testing.T) {
assert.Regexp(t, "pop", err)
}

func TestCreateTokenPoolOperationFail(t *testing.T) {
func TestCreateTokenPoolOpInsertFail(t *testing.T) {
am, cancel := newTestAssets(t)
defer cancel()

Expand All @@ -257,6 +257,31 @@ func TestCreateTokenPoolOperationFail(t *testing.T) {
assert.Regexp(t, "pop", err)
}

func TestCreateTokenPoolOpUpdateFail(t *testing.T) {
am, cancel := newTestAssets(t)
defer cancel()

pool := &fftypes.TokenPool{
Connector: "magic-tokens",
Name: "testpool",
}

mdi := am.database.(*databasemocks.Plugin)
mdm := am.data.(*datamocks.Manager)
mti := am.tokens["magic-tokens"].(*tokenmocks.Plugin)
mim := am.identity.(*identitymanagermocks.Manager)
mth := am.txHelper.(*txcommonmocks.Helper)
mim.On("GetLocalOrganization", context.Background()).Return(&fftypes.Organization{Identity: "0x12345"}, nil)
mdm.On("VerifyNamespaceExists", context.Background(), "ns1").Return(nil)
mth.On("SubmitNewTransaction", context.Background(), "ns1", fftypes.TransactionTypeTokenPool).Return(fftypes.NewUUID(), nil)
mdi.On("InsertOperation", context.Background(), mock.Anything).Return(nil)
mti.On("CreateTokenPool", context.Background(), mock.Anything, mock.Anything, mock.Anything).Return(true, nil)
mdi.On("UpdateOperation", context.Background(), mock.Anything, mock.Anything).Return(fmt.Errorf("pop"))

_, err := am.CreateTokenPool(context.Background(), "ns1", pool, false)
assert.Regexp(t, "pop", err)
}

func TestCreateTokenPoolSuccess(t *testing.T) {
am, cancel := newTestAssets(t)
defer cancel()
Expand All @@ -273,7 +298,7 @@ func TestCreateTokenPoolSuccess(t *testing.T) {
mth := am.txHelper.(*txcommonmocks.Helper)
mim.On("GetLocalOrganization", context.Background()).Return(&fftypes.Organization{Identity: "0x12345"}, nil)
mdm.On("VerifyNamespaceExists", context.Background(), "ns1").Return(nil)
mti.On("CreateTokenPool", context.Background(), mock.Anything, mock.Anything, mock.Anything).Return(nil)
mti.On("CreateTokenPool", context.Background(), mock.Anything, mock.Anything, mock.Anything).Return(false, nil)
mth.On("SubmitNewTransaction", context.Background(), "ns1", fftypes.TransactionTypeTokenPool).Return(fftypes.NewUUID(), nil)
mdi.On("InsertOperation", context.Background(), mock.Anything).Return(nil)

Expand All @@ -298,7 +323,7 @@ func TestCreateTokenPoolConfirm(t *testing.T) {
mth := am.txHelper.(*txcommonmocks.Helper)
mim.On("GetLocalOrganization", context.Background()).Return(&fftypes.Organization{Identity: "0x12345"}, nil)
mdm.On("VerifyNamespaceExists", context.Background(), "ns1").Return(nil).Times(2)
mti.On("CreateTokenPool", context.Background(), mock.Anything, mock.Anything).Return(nil).Times(1)
mti.On("CreateTokenPool", context.Background(), mock.Anything, mock.Anything).Return(false, nil).Times(1)
mth.On("SubmitNewTransaction", context.Background(), "ns1", fftypes.TransactionTypeTokenPool).Return(fftypes.NewUUID(), nil)
mdi.On("InsertOperation", context.Background(), mock.Anything).Return(nil).Times(1)
msa.On("WaitForTokenPool", context.Background(), "ns1", mock.Anything, mock.Anything).
Expand All @@ -323,9 +348,13 @@ func TestActivateTokenPool(t *testing.T) {
ev := &fftypes.BlockchainEvent{}

mdm := am.data.(*datamocks.Manager)
mdi := am.database.(*databasemocks.Plugin)
mti := am.tokens["magic-tokens"].(*tokenmocks.Plugin)
mdm.On("VerifyNamespaceExists", context.Background(), "ns1").Return(nil)
mti.On("ActivateTokenPool", context.Background(), mock.Anything, pool, ev).Return(nil)
mdi.On("InsertOperation", context.Background(), mock.MatchedBy(func(op *fftypes.Operation) bool {
return op.Type == fftypes.OpTypeTokenActivatePool
})).Return(nil)
mti.On("ActivateTokenPool", context.Background(), mock.Anything, pool, ev).Return(false, nil)

err := am.ActivateTokenPool(context.Background(), pool, ev)
assert.NoError(t, err)
Expand All @@ -348,6 +377,74 @@ func TestActivateTokenPoolBadConnector(t *testing.T) {
assert.Regexp(t, "FF10272", err)
}

func TestActivateTokenPoolOpInsertFail(t *testing.T) {
am, cancel := newTestAssets(t)
defer cancel()

pool := &fftypes.TokenPool{
Namespace: "ns1",
Connector: "magic-tokens",
}
ev := &fftypes.BlockchainEvent{}

mdm := am.data.(*datamocks.Manager)
mdi := am.database.(*databasemocks.Plugin)
mdm.On("VerifyNamespaceExists", context.Background(), "ns1").Return(nil)
mdi.On("InsertOperation", context.Background(), mock.MatchedBy(func(op *fftypes.Operation) bool {
return op.Type == fftypes.OpTypeTokenActivatePool
})).Return(fmt.Errorf("pop"))

err := am.ActivateTokenPool(context.Background(), pool, ev)
assert.EqualError(t, err, "pop")
}

func TestActivateTokenPoolFail(t *testing.T) {
am, cancel := newTestAssets(t)
defer cancel()

pool := &fftypes.TokenPool{
Namespace: "ns1",
Connector: "magic-tokens",
}
ev := &fftypes.BlockchainEvent{}

mdm := am.data.(*datamocks.Manager)
mdi := am.database.(*databasemocks.Plugin)
mti := am.tokens["magic-tokens"].(*tokenmocks.Plugin)
mdm.On("VerifyNamespaceExists", context.Background(), "ns1").Return(nil)
mdi.On("InsertOperation", context.Background(), mock.MatchedBy(func(op *fftypes.Operation) bool {
return op.Type == fftypes.OpTypeTokenActivatePool
})).Return(nil)
mti.On("ActivateTokenPool", context.Background(), mock.Anything, pool, ev).Return(false, fmt.Errorf("pop"))

err := am.ActivateTokenPool(context.Background(), pool, ev)
assert.EqualError(t, err, "pop")
}

func TestActivateTokenPoolOpUpdateFail(t *testing.T) {
am, cancel := newTestAssets(t)
defer cancel()

pool := &fftypes.TokenPool{
Namespace: "ns1",
Connector: "magic-tokens",
}
ev := &fftypes.BlockchainEvent{}

mdm := am.data.(*datamocks.Manager)
mdi := am.database.(*databasemocks.Plugin)
mti := am.tokens["magic-tokens"].(*tokenmocks.Plugin)
mdm.On("VerifyNamespaceExists", context.Background(), "ns1").Return(nil)
mdi.On("InsertOperation", context.Background(), mock.MatchedBy(func(op *fftypes.Operation) bool {
return op.Type == fftypes.OpTypeTokenActivatePool
})).Return(nil)
mti.On("ActivateTokenPool", context.Background(), mock.Anything, pool, ev).Return(true, nil)
mdi.On("UpdateOperation", context.Background(), mock.Anything, mock.Anything).Return(fmt.Errorf("pop"))

err := am.ActivateTokenPool(context.Background(), pool, ev)
assert.EqualError(t, err, "pop")
}

func TestGetTokenPool(t *testing.T) {
am, cancel := newTestAssets(t)
defer cancel()
Expand Down
2 changes: 1 addition & 1 deletion internal/contracts/manager.go
Original file line number Diff line number Diff line change
Expand Up @@ -188,7 +188,7 @@ func (cm *contractManager) InvokeContract(ctx context.Context, ns string, req *f
ns,
txid,
"",
fftypes.OpTypeContractInvoke)
fftypes.OpTypeBlockchainInvoke)
op.Input = req.Input
return cm.database.InsertOperation(ctx, op)
})
Expand Down
8 changes: 4 additions & 4 deletions internal/contracts/manager_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -994,7 +994,7 @@ func TestInvokeContract(t *testing.T) {

mim.On("ResolveSigningKey", mock.Anything, "").Return("key-resolved", nil)
mdi.On("InsertOperation", mock.Anything, mock.MatchedBy(func(op *fftypes.Operation) bool {
return op.Namespace == "ns1" && op.Type == fftypes.OpTypeContractInvoke && op.Plugin == "mockblockchain"
return op.Namespace == "ns1" && op.Type == fftypes.OpTypeBlockchainInvoke && op.Plugin == "mockblockchain"
})).Return(nil)
mbi.On("InvokeContract", mock.Anything, mock.AnythingOfType("*fftypes.UUID"), "key-resolved", req.Location, req.Method, req.Input).Return(struct{}{}, nil)

Expand Down Expand Up @@ -1170,7 +1170,7 @@ func TestQueryContract(t *testing.T) {
mim.On("ResolveSigningKey", mock.Anything, "").Return("key-resolved", nil)
mth.On("SubmitNewTransaction", mock.Anything, "ns1", fftypes.TransactionTypeContractInvoke).Return(fftypes.NewUUID(), nil)
mdi.On("InsertOperation", mock.Anything, mock.MatchedBy(func(op *fftypes.Operation) bool {
return op.Namespace == "ns1" && op.Type == fftypes.OpTypeContractInvoke && op.Plugin == "mockblockchain"
return op.Namespace == "ns1" && op.Type == fftypes.OpTypeBlockchainInvoke && op.Plugin == "mockblockchain"
})).Return(nil)
mbi.On("QueryContract", mock.Anything, req.Location, req.Method, req.Input).Return(struct{}{}, nil)

Expand Down Expand Up @@ -1200,7 +1200,7 @@ func TestCallContractInvalidType(t *testing.T) {
mim.On("ResolveSigningKey", mock.Anything, "").Return("key-resolved", nil)
mth.On("SubmitNewTransaction", mock.Anything, "ns1", fftypes.TransactionTypeContractInvoke).Return(fftypes.NewUUID(), nil)
mdi.On("InsertOperation", mock.Anything, mock.MatchedBy(func(op *fftypes.Operation) bool {
return op.Namespace == "ns1" && op.Type == fftypes.OpTypeContractInvoke && op.Plugin == "mockblockchain"
return op.Namespace == "ns1" && op.Type == fftypes.OpTypeBlockchainInvoke && op.Plugin == "mockblockchain"
})).Return(nil)

assert.PanicsWithValue(t, "unknown call type: ", func() {
Expand Down Expand Up @@ -1352,7 +1352,7 @@ func TestInvokeContractAPI(t *testing.T) {
mdb.On("GetFFIMethod", mock.Anything, "ns1", mock.Anything, mock.Anything).Return(&fftypes.FFIMethod{Name: "peel"}, nil)
mth.On("SubmitNewTransaction", mock.Anything, "ns1", fftypes.TransactionTypeContractInvoke).Return(fftypes.NewUUID(), nil)
mdi.On("InsertOperation", mock.Anything, mock.MatchedBy(func(op *fftypes.Operation) bool {
return op.Namespace == "ns1" && op.Type == fftypes.OpTypeContractInvoke && op.Plugin == "mockblockchain"
return op.Namespace == "ns1" && op.Type == fftypes.OpTypeBlockchainInvoke && op.Plugin == "mockblockchain"
})).Return(nil)
mbi.On("InvokeContract", mock.Anything, mock.AnythingOfType("*fftypes.UUID"), "key-resolved", req.Location, mock.AnythingOfType("*fftypes.FFIMethod"), req.Input).Return(struct{}{}, nil)

Expand Down
26 changes: 0 additions & 26 deletions internal/definitions/definition_handler_tokenpool.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,35 +24,9 @@ import (
"github.com/hyperledger/firefly/pkg/fftypes"
)

func (dh *definitionHandlers) confirmPoolAnnounceOp(ctx context.Context, pool *fftypes.TokenPool) error {
// Find a matching operation within this transaction
fb := database.OperationQueryFactory.NewFilter(ctx)
filter := fb.And(
fb.Eq("tx", pool.TX.ID),
fb.Eq("type", fftypes.OpTypeTokenAnnouncePool),
)
if operations, _, err := dh.database.GetOperations(ctx, filter); err != nil {
return err
} else if len(operations) > 0 {
op := operations[0]
update := database.OperationQueryFactory.NewUpdate(ctx).
Set("status", fftypes.OpStatusSucceeded).
Set("output", fftypes.JSONObject{"message": pool.Message})
if err := dh.database.UpdateOperation(ctx, op.ID, update); err != nil {
return err
}
}
return nil
}

func (dh *definitionHandlers) persistTokenPool(ctx context.Context, announce *fftypes.TokenPoolAnnouncement) (valid bool, err error) {
pool := announce.Pool

// Mark announce operation (if any) completed
if err := dh.confirmPoolAnnounceOp(ctx, pool); err != nil {
return false, err // retryable
}

// Create the pool in pending state
pool.State = fftypes.TokenPoolStatePending
err = dh.database.UpsertTokenPool(ctx, pool)
Expand Down
Loading