Giter Site home page Giter Site logo

token-sdk's Introduction

Corda

License

Corda

Corda is an open source blockchain project, designed for business from the start. Only Corda allows you to build interoperable blockchain networks that transact in strict privacy. Corda's smart contract technology allows businesses to transact directly, with value.

Architecture Evolution

The code present in this repository reflects the first version of the implementation of the Corda model for DLT technology. This first architecture version covers Corda versions 1 through 4 and continues to deliver on the promise of DLT for both the open source community and industry as a whole.

However, like all things, Corda must evolve to serve the more stringent needs of today. This is why the second (and current) version of the Corda Architecture can be found here and will form the basis of the Corda 5 release.

Features

  • Smart contracts that can be written in Java and other JVM languages
  • Flow framework to manage communication and negotiation between participants
  • Peer-to-peer network of nodes
  • "Notary" infrastructure to validate uniqueness and sequencing of transactions without global broadcast
  • Enables the development and deployment of distributed apps called CorDapps
  • Written in Kotlin, targeting the JVM

Getting started

  1. Read the Getting Started documentation
  2. Run the Example CorDapp
  3. Read about Corda's Key Concepts
  4. Follow the Hello, World! tutorial

Useful links

Contributing

Corda is an open-source project and contributions are welcome!

To find out how to contribute, please see our contributing docs.

License

Apache 2.0

Acknowledgements

YourKit

YourKit supports open source projects with its full-featured Java Profiler.

YourKit, LLC is the creator of YourKit Java Profiler and YourKit .NET Profiler, innovative and intelligent tools for profiling Java and .NET applications.

token-sdk's People

Contributors

adagys avatar adelel1 avatar afurgal avatar agoldvarg avatar alex-koller-r3 avatar andr3ej avatar caismanai avatar chrisr3 avatar clintonio avatar davidleeuk avatar dhrudevalia avatar exfalso avatar illoyd avatar ischasny avatar jxilt avatar kasiastreich avatar m4ksio avatar mcgovc avatar mikehearn avatar nargas-ritu avatar philippkueng avatar r3domfox avatar rajvjn avatar rick-r3 avatar roastario avatar rogersanick avatar ronanbrowne avatar shamsasari avatar tb-pq avatar willhr3 avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

token-sdk's Issues

Error with Initiating Flow ConfidentialMoveFungibleTokens()

Operating System: Windows 10
Corda: 4.3
tokens_release_version = '1.1-RC06-PRESIGN'
Testing with a MockNetwork

I hope I am not making a rookie mistake but I am getting an error when I call:

ConfidentialMoveFungibleTokens(partyAndAmount, observers, queryCriteria, changeHolder));

  1. The error occurs ONLY if there is change. If there is an amount in the vault that exactly matches the move request then no error occurs.

  2. The vault does not get updated (i.e. no states are consumed and no tokens are moved).

Here is the error:

java.lang.IllegalArgumentException: You must provide sessions for all parties.
at com.r3.corda.lib.tokens.workflows.internal.flows.confidential.AnonymisePartiesFlow.call(AnonymisePartiesFlow.kt:23) ~[tokens-workflows-1.1-RC06-PRESIGN.jar:?]
at com.r3.corda.lib.tokens.workflows.internal.flows.confidential.AnonymisePartiesFlow.call(AnonymisePartiesFlow.kt:16) ~[tokens-workflows-1.1-RC06-PRESIGN.jar:?]
at net.corda.node.services.statemachine.FlowStateMachineImpl.subFlow(FlowStateMachineImpl.kt:330) ~[corda-node-4.3.jar:?]
at net.corda.core.flows.FlowLogic.subFlow(FlowLogic.kt:326) ~[corda-core-4.3.jar:?]
at com.r3.corda.lib.tokens.workflows.flows.confidential.ConfidentialTokensFlow.call(ConfidentialTokensFlow.kt:41) ~[tokens-workflows-1.1-RC06-PRESIGN.jar:?]
at com.r3.corda.lib.tokens.workflows.flows.confidential.ConfidentialTokensFlow.call(ConfidentialTokensFlow.kt:28) ~[tokens-workflows-1.1-RC06-PRESIGN.jar:?]
at net.corda.node.services.statemachine.FlowStateMachineImpl.subFlow(FlowStateMachineImpl.kt:330) ~[corda-node-4.3.jar:?]
at net.corda.core.flows.FlowLogic.subFlow(FlowLogic.kt:326) ~[corda-core-4.3.jar:?]
at com.r3.corda.lib.tokens.workflows.flows.move.ConfidentialMoveFungibleTokensFlow.call(ConfidentialMoveFungibleTokensFlow.kt:63) ~[tokens-workflows-1.1-RC06-PRESIGN.jar:?]
at com.r3.corda.lib.tokens.workflows.flows.move.ConfidentialMoveFungibleTokensFlow.call(ConfidentialMoveFungibleTokensFlow.kt:30) ~[tokens-workflows-1.1-RC06-PRESIGN.jar:?]
at net.corda.node.services.statemachine.FlowStateMachineImpl.subFlow(FlowStateMachineImpl.kt:330) ~[corda-node-4.3.jar:?]
at net.corda.core.flows.FlowLogic.subFlow(FlowLogic.kt:326) ~[corda-core-4.3.jar:?]
at com.r3.corda.lib.tokens.workflows.flows.rpc.ConfidentialMoveFungibleTokens.call(MoveTokens.kt:149) ~[tokens-workflows-1.1-RC06-PRESIGN.jar:?]
at com.r3.corda.lib.tokens.workflows.flows.rpc.ConfidentialMoveFungibleTokens.call(MoveTokens.kt:120) ~[tokens-workflows-1.1-RC06-PRESIGN.jar:?]
at net.corda.node.services.statemachine.FlowStateMachineImpl.subFlow(FlowStateMachineImpl.kt:330) ~[corda-node-4.3.jar:?]
at net.corda.core.flows.FlowLogic.subFlow(FlowLogic.kt:326) ~[corda-core-4.3.jar:?]
at com.template.flows.USDConfidentialMove.call(USDConfidentialMove.java:78) ~[main/:?]
at com.template.flows.USDConfidentialMove.call(USDConfidentialMove.java:27) ~[main/:?]
at net.corda.node.services.statemachine.FlowStateMachineImpl.run(FlowStateMachineImpl.kt:270) ~[corda-node-4.3.jar:?]
at net.corda.node.services.statemachine.FlowStateMachineImpl.run(FlowStateMachineImpl.kt:46) ~[corda-node-4.3.jar:?]
at co.paralleluniverse.fibers.Fiber.run1(Fiber.java:1092) ~[quasar-core-0.7.10-jdk8.jar:0.7.10]
at co.paralleluniverse.fibers.Fiber.exec(Fiber.java:788) ~[quasar-core-0.7.10-jdk8.jar:0.7.10]
at co.paralleluniverse.fibers.RunnableFiberTask.doExec(RunnableFiberTask.java:100) ~[quasar-core-0.7.10-jdk8.jar:0.7.10]
at co.paralleluniverse.fibers.RunnableFiberTask.run(RunnableFiberTask.java:91) ~[quasar-core-0.7.10-jdk8.jar:0.7.10]
at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511) ~[?:1.8.0_192]
at java.util.concurrent.FutureTask.run(FutureTask.java:266) ~[?:1.8.0_192]
at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.access$201(ScheduledThreadPoolExecutor.java:180) ~[?:1.8.0_192]
at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:293) ~[?:1.8.0_192]
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149) ~[?:1.8.0_192]
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624) ~[?:1.8.0_192]
at net.corda.node.utilities.AffinityExecutor$ServiceAffinityExecutor$1$thread$1.run(AffinityExecutor.kt:63) ~[corda-node-4.3.jar:?]

Let me know if I can provide more information. I will test ConfidentialRedeemFungibleTokens() next.

Distributing EvolvableToken updates

Apologies for hijacking an issue, but how should one distribute EvolvableToken updates to the whole network? A distribution list probably makes sense for updating a subset of the network's nodes, so i suppose i should get a network map snapshot, filter out participants and broadcast manually?

DistributionRecord error with 1.1-RC02+ on Corda Enterprise 4.2

Upgrading from 1.1-RC01 to 1.1-RC02 or 1.1-RC05* seems to break our cordapps on Corda Enterprise 4.2.

java.lang.IllegalArgumentException: Not an entity: class com.r3.corda.lib.tokens.workflows.internal.schemas.DistributionRecord
        at org.hibernate.metamodel.internal.MetamodelImpl.entity(MetamodelImpl.java:536) ~[hibernate-core-5.3.10.Final.jar:5.3.10.Final]
        at org.hibernate.query.criteria.internal.QueryStructure.from(QueryStructure.java:126) ~[hibernate-core-5.3.10.Final.jar:5.3.10.Final]
        at org.hibernate.query.criteria.internal.CriteriaQueryImpl.from(CriteriaQueryImpl.java:153) ~[hibernate-core-5.3.10.Final.jar:5.3.10.Final]
        at com.r3.corda.lib.tokens.workflows.internal.flows.distribution.DistributionUtilitiesKt$getDistributionRecord$1.invoke(DistributionUtilities.kt:39) ~[tokens-workflows-1.1-RC05.jar:?]
        at com.r3.corda.lib.tokens.workflows.internal.flows.distribution.DistributionUtilitiesKt$getDistributionRecord$1.invoke(DistributionUtilities.kt) ~[tokens-workflows-1.1-RC05.jar:?]
        at net.corda.node.internal.AbstractNode$ServiceHubInternalImpl.withEntityManager(AbstractNode.kt:1115) ~[corda-node-4.2.jar:?]
        at com.r3.corda.lib.tokens.workflows.internal.flows.distribution.DistributionUtilitiesKt.getDistributionRecord(DistributionUtilities.kt:36) ~[tokens-workflows-1.1-RC05.jar:?]
        at com.r3.corda.lib.tokens.workflows.internal.flows.distribution.DistributionUtilitiesKt.hasDistributionRecord(DistributionUtilities.kt:50) ~[tokens-workflows-1.1-RC05.jar:?]
        at com.r3.corda.lib.tokens.workflows.utilities.FlowUtilitiesKt.addPartyToDistributionList(FlowUtilities.kt:28) ~[tokens-workflows-1.1-RC05.jar:?]
        at com.r3.corda.lib.tokens.workflows.internal.flows.distribution.DistributionUtilitiesKt.addToDistributionList(DistributionUtilities.kt:70) ~[tokens-workflows-1.1-RC05.jar:?]
        at com.r3.corda.lib.tokens.workflows.internal.flows.distribution.UpdateDistributionListFlow.call(UpdateDistributionListFlow.kt:53) ~[tokens-workflows-1.1-RC05.jar:?]
        at com.r3.corda.lib.tokens.workflows.internal.flows.distribution.UpdateDistributionListFlow.call(UpdateDistributionListFlow.kt:17) ~[tokens-workflows-1.1-RC05.jar:?]
        at net.corda.node.services.statemachine.FlowStateMachineImpl.subFlow(FlowStateMachineImpl.kt:333) ~[corda-node-4.2.jar:?]
        at net.corda.core.flows.FlowLogic.subFlow(FlowLogic.kt:314) ~[corda-core-4.2.jar:?]
        at com.r3.corda.lib.tokens.workflows.flows.issue.IssueTokensFlow.call(IssueTokensFlow.kt:91) ~[tokens-workflows-1.1-RC05.jar:?]
        at com.r3.corda.lib.tokens.workflows.flows.issue.IssueTokensFlow.call(IssueTokensFlow.kt:46) ~[tokens-workflows-1.1-RC05.jar:?]
        at net.corda.node.services.statemachine.FlowStateMachineImpl.subFlow(FlowStateMachineImpl.kt:333) ~[corda-node-4.2.jar:?]
        at net.corda.core.flows.FlowLogic.subFlow(FlowLogic.kt:314) ~[corda-core-4.2.jar:?]

MoveToken works with C4 but fails with Corda 5.0-SNAPSHOT

MoveToken works for me on C4 but throws the following error when using Corda 5.0-SNAPSHOT:

 java.lang.IllegalStateException: The LinearState with ID 03fbddaa-205f-42a0-b7c9-2f8c1c6b17c8 is unknown to this node or it has been exited from the ledger.
        at net.corda.core.contracts.LinearPointer.resolve(StatePointer.kt:113) ~[corda-core-5.0-SNAPSHOT.jar:?]
        at net.corda.core.transactions.TransactionBuilder.resolveStatePointers(TransactionBuilder.kt:530) ~[corda-core-5.0-SNAPSHOT.jar:?]
        at net.corda.core.transactions.TransactionBuilder.addInputState(TransactionBuilder.kt:584) ~[corda-core-5.0-SNAPSHOT.jar:?]
        at com.r3.corda.sdk.token.workflow.selection.TokenSelection.generateMove(TokenSelection.kt:231) ~[workflow-1.0-SNAPSHOT.jar:?]
        at com.r3.corda.sdk.token.workflow.selection.TokenSelection.generateMove(TokenSelection.kt:143) ~[workflow-1.0-SNAPSHOT.jar:?]
        at com.r3.corda.sdk.token.workflow.selection.TokenSelection.generateMove$default(TokenSelection.kt:141) ~[workflow-1.0-SNAPSHOT.jar:?]
        at com.r3.corda.sdk.token.workflow.flows.MoveToken$Initiator.call(MoveToken.kt:52) ~[workflow-1.0-SNAPSHOT.jar:?]
        at com.r3.corda.sdk.token.workflow.flows.MoveToken$Initiator.call(MoveToken.kt:30) ~[workflow-1.0-SNAPSHOT.jar:?]
        at net.corda.node.services.statemachine.FlowStateMachineImpl.subFlow(FlowStateMachineImpl.kt:290) ~[corda-node-5.0-SNAPSHOT.jar:?]
        at net.corda.core.flows.FlowLogic.subFlow(FlowLogic.kt:311) ~[corda-core-5.0-SNAPSHOT.jar:?]
        at foobar.MoveFungibleTokenFlow.call(MoveFungibleTokenFlow.kt:44) ~[cordapp-workflow-0.19-SNAPSHOT.jar:?]
        at foobar.MoveFungibleTokenFlow.call(MoveFungibleTokenFlow.kt:22) ~[cordapp-workflow-0.19-SNAPSHOT.jar:?]
        at net.corda.node.services.statemachine.FlowStateMachineImpl.subFlow(FlowStateMachineImpl.kt:290) ~[corda-node-5.0-SNAPSHOT.jar:?]
        at net.corda.core.flows.FlowLogic.subFlow(FlowLogic.kt:311) ~[corda-core-5.0-SNAPSHOT.jar:?]
        at foobar.TransferAllowOrDenyFlow.makeTransfer(TranferWorkflow.kt:136) ~[cordapp-workflow-0.19-SNAPSHOT.jar:?]
        at foobar.TransferAllowOrDenyFlow.processInput(TranferWorkflow.kt:108) ~[cordapp-workflow-0.19-SNAPSHOT.jar:?]
        at com.github.manosbatsis.partiture.flow.PartitureFlow.call(PartitureFlow.kt:102) ~[cordapp-workflow-0.19-SNAPSHOT.jar:?]
        at net.corda.node.services.statemachine.FlowStateMachineImpl.run(FlowStateMachineImpl.kt:228) ~[corda-node-5.0-SNAPSHOT.jar:?]
        at net.corda.node.services.statemachine.FlowStateMachineImpl.run(FlowStateMachineImpl.kt:45) ~[corda-node-5.0-SNAPSHOT.jar:?]
        at co.paralleluniverse.fibers.Fiber.run1(Fiber.java:1092) ~[quasar-core-0.7.10-jdk8.jar:0.7.10]
        at co.paralleluniverse.fibers.Fiber.exec(Fiber.java:788) ~[quasar-core-0.7.10-jdk8.jar:0.7.10]
        at co.paralleluniverse.fibers.RunnableFiberTask.doExec(RunnableFiberTask.java:100) ~[quasar-core-0.7.10-jdk8.jar:0.7.10]
        at co.paralleluniverse.fibers.RunnableFiberTask.run(RunnableFiberTask.java:91) ~[quasar-core-0.7.10-jdk8.jar:0.7.10]
        at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511) ~[?:1.8.0_181]
        at java.util.concurrent.FutureTask.run(FutureTask.java:266) ~[?:1.8.0_181]
        at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.access$201(ScheduledThreadPoolExecutor.java:180) ~[?:1.8.0_181]
        at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:293) ~[?:1.8.0_181]
        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149) ~[?:1.8.0_181]
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624) ~[?:1.8.0_181]
        at net.corda.node.utilities.AffinityExecutor$ServiceAffinityExecutor$1$thread$1.run(AffinityExecutor.kt:63) ~[corda-node-5.0-SNAPSHOT.jar:?

DriverDSLImpl issue with 1.1-RC01/master and CE 4.2

I'm using Corda Enterprise 4.2. When i try to change tokens SDK version to 1.1-RC01 or master i get the folowing error. I don't know how the SDK could possibly effect DriverDSLImpl and/or starting the test notary, but everything works as soon as i revert to the much older 1.1-SNAPSHOT.

    [INFO] 17:23:10,554 [driver-pool-thread-1] internal.Node.makeStateMachineExecutorService - Multi-threaded state machine manager with 1 threads.
    [INFO] 17:23:10,588 [driver-pool-thread-1] statemachine.StaffedFlowHospital.<init> - Initializing Flow Hospital. Session initialization error treatment disabled.
    [INFO] 17:23:10,611 [driver-pool-thread-1] internal.Node.start - Node starting up ...
    [INFO] 17:23:10,649 [driver-pool-thread-1] internal.NodeFlowManager.registerInitiatedFlow - Registered com.r3.corda.lib.tokens.workflows.flows.rpc.ConfidentialIssueTokens to initiate com.r3.corda.lib.tokens.workflows.flows.rpc.ConfidentialIssueTokensHandler (version 1)
    [INFO] 17:23:10,650 [driver-pool-thread-1] internal.NodeFlowManager.registerInitiatedFlow - Registered com.r3.corda.lib.tokens.workflows.flows.rpc.ConfidentialMoveFungibleTokens to initiate com.r3.corda.lib.tokens.workflows.flows.rpc.ConfidentialMoveFungibleTokensHandler (version 1)
    [INFO] 17:23:10,650 [driver-pool-thread-1] internal.NodeFlowManager.registerInitiatedFlow - Registered com.r3.corda.lib.tokens.workflows.flows.rpc.ConfidentialMoveNonFungibleTokens to initiate com.r3.corda.lib.tokens.workflows.flows.rpc.ConfidentialMoveNonFungibleTokensHandler (version 1)
    [INFO] 17:23:10,650 [driver-pool-thread-1] internal.NodeFlowManager.registerInitiatedFlow - Registered com.r3.corda.lib.tokens.workflows.flows.rpc.ConfidentialRedeemFungibleTokens to initiate com.r3.corda.lib.tokens.workflows.flows.rpc.ConfidentialRedeemFungibleTokensHandler (version 1)
    [INFO] 17:23:10,650 [driver-pool-thread-1] internal.NodeFlowManager.registerInitiatedFlow - Registered com.r3.corda.lib.tokens.workflows.flows.rpc.CreateEvolvableTokens to initiate com.r3.corda.lib.tokens.workflows.flows.rpc.CreateEvolvableTokensHandler (version 1)
    [INFO] 17:23:10,651 [driver-pool-thread-1] internal.NodeFlowManager.registerInitiatedFlow - Registered com.r3.corda.lib.tokens.workflows.flows.rpc.IssueTokens to initiate com.r3.corda.lib.tokens.workflows.flows.rpc.IssueTokensHandler (version 1)
    [INFO] 17:23:10,651 [driver-pool-thread-1] internal.NodeFlowManager.registerInitiatedFlow - Registered com.r3.corda.lib.tokens.workflows.flows.rpc.MoveFungibleTokens to initiate com.r3.corda.lib.tokens.workflows.flows.rpc.MoveFungibleTokensHandler (version 1)
    [INFO] 17:23:10,651 [driver-pool-thread-1] internal.NodeFlowManager.registerInitiatedFlow - Registered com.r3.corda.lib.tokens.workflows.flows.rpc.MoveNonFungibleTokens to initiate com.r3.corda.lib.tokens.workflows.flows.rpc.MoveNonFungibleTokensHandler (version 1)
    [INFO] 17:23:10,651 [driver-pool-thread-1] internal.NodeFlowManager.registerInitiatedFlow - Registered com.r3.corda.lib.tokens.workflows.flows.rpc.RedeemFungibleTokens to initiate com.r3.corda.lib.tokens.workflows.flows.rpc.RedeemFungibleTokensHandler (version 1)
    [INFO] 17:23:10,651 [driver-pool-thread-1] internal.NodeFlowManager.registerInitiatedFlow - Registered com.r3.corda.lib.tokens.workflows.flows.rpc.RedeemNonFungibleTokens to initiate com.r3.corda.lib.tokens.workflows.flows.rpc.RedeemNonFungibleTokensHandler (version 1)
    [INFO] 17:23:10,652 [driver-pool-thread-1] internal.NodeFlowManager.registerInitiatedFlow - Registered com.r3.corda.lib.tokens.workflows.flows.rpc.UpdateEvolvableToken to initiate com.r3.corda.lib.tokens.workflows.flows.rpc.UpdateEvolvableTokenHandler (version 1)
    [INFO] 17:23:10,652 [driver-pool-thread-1] internal.NodeFlowManager.registerInitiatedFlow - Registered com.r3.corda.lib.tokens.workflows.internal.flows.distribution.RequestAdditionToDistributionList$Initiator to initiate com.r3.corda.lib.tokens.workflows.internal.flows.distribution.RequestAdditionToDistributionList$Responder (version 1)
    [INFO] 17:23:10,653 [driver-pool-thread-1] internal.NodeFlowManager.registerInitiatedFlow - Registered com.r3.corda.lib.tokens.workflows.internal.flows.distribution.UpdateDistributionListFlow to initiate com.r3.corda.lib.tokens.workflows.internal.flows.distribution.UpdateDistributionListFlowHandler (version 1)
    [ERROR] 17:25:09,655 [DefaultDispatcher-worker-1 @coroutine#1] internal.DriverDSLImpl.genericDriver - Driver shutting down because of exception [errorCode=1crywct, moreInformationAt=https://errors.corda.net/ENT/4.2/1crywct]
     java.lang.IllegalStateException: Unable to start notaries. A required port might be bound already.
        at net.corda.testing.node.internal.DriverDSLImpl.start(DriverDSLImpl.kt:388) ~[corda-node-driver-4.2.jar:?]
        at net.corda.testing.node.internal.DriverDSLImplKt.genericDriver(DriverDSLImpl.kt:1005) ~[corda-node-driver-4.2.jar:?]
        at net.corda.testing.driver.Driver.driver(Driver.kt:190) ~[corda-node-driver-4.2.jar:?]
        at com.github.manosbatsis.corbeans.test.integration.NodeDriverHelper.withDriverNodes(NodeDriverHelper.kt:200) ~[corbeans-spring-boot-starter-test-0.30.jar:?]
        at com.github.manosbatsis.corbeans.test.integration.NodeDriverHelper$startNetworkAsync$1.doResume(NodeDriverHelper.kt:163) ~[corbeans-spring-boot-starter-test-0.30.jar:?]
        at kotlin.coroutines.experimental.jvm.internal.CoroutineImpl.resume(CoroutineImpl.kt:42) ~[kotlin-stdlib-1.2.71.jar:1.2.71-release-64 (1.2.71)]
        at kotlinx.coroutines.experimental.DispatchedTask$DefaultImpls.run(Dispatched.kt:168) ~[kotlinx-coroutines-core-0.30.2.jar:?]
        at kotlinx.coroutines.experimental.DispatchedContinuation.run(Dispatched.kt:13) ~[kotlinx-coroutines-core-0.30.2.jar:?]
        at kotlinx.coroutines.experimental.scheduling.Task.run(Tasks.kt:94) ~[kotlinx-coroutines-core-0.30.2.jar:?]
        at kotlinx.coroutines.experimental.scheduling.CoroutineScheduler.runSafely(CoroutineScheduler.kt:586) ~[kotlinx-coroutines-core-0.30.2.jar:?]
        at kotlinx.coroutines.experimental.scheduling.CoroutineScheduler.access$runSafely(CoroutineScheduler.kt:60) ~[kotlinx-coroutines-core-0.30.2.jar:?]
        at kotlinx.coroutines.experimental.scheduling.CoroutineScheduler$Worker.run(CoroutineScheduler.kt:732) ~[kotlinx-coroutines-core-0.30.2.jar:?]
    Caused by: java.util.concurrent.TimeoutException
        at java.util.concurrent.CompletableFuture.timedGet(CompletableFuture.java:1771) ~[?:1.8.0_212]
        at java.util.concurrent.CompletableFuture.get(CompletableFuture.java:1915) ~[?:1.8.0_212]
        at net.corda.core.internal.concurrent.CordaFutureImpl.get(CordaFutureImpl.kt) ~[corda-core-4.2.jar:?]
        at net.corda.core.internal.concurrent.CordaFutureImplKt.get(CordaFutureImpl.kt:172) ~[corda-core-4.2.jar:?]
        at net.corda.core.utilities.KotlinUtilsKt.getOrThrow(KotlinUtils.kt:137) ~[corda-core-4.2.jar:?]
        at net.corda.testing.node.internal.DriverDSLImpl.start(DriverDSLImpl.kt:384) ~[corda-node-driver-4.2.jar:?]
        ... 11 more
    [INFO] 17:25:09,733 [Log4j2-TF-1-AsyncLogger[AsyncContextNoThreadLocal@73d16e93]-1] manifests.Manifests.info - 156 attributes loaded from 358 stream(s) in 64ms, 156 saved, 4947 ignored: ["ActiveMQ-Version", "Agent-Class", "Ant-Version", "Application-Class", "Application-ID", "Application-Library-Allowable-Codebase", "Application-Name", "Application-Version", "Apr-Version", "Archiver-Version", "Automatic-Module-Name", "Bnd-LastModified", "Boot-Class-Path", "BoringSSL-Branch", "BoringSSL-Revision", "Branch", "Build-Date", "Build-Host", "Build-Id", "Build-Java-Version", "Build-Jdk", "Build-Jdk-Spec", "Build-Job", "Build-Number", "Build-Revision", "Build-Time", "Build-Timestamp", "Built-By", "Built-Date", "Built-OS", "Built-On", "Built-Status", "Built-With", "Bundle-ActivationPolicy", "Bundle-Activator", "Bundle-Category", "Bundle-ClassPath", "Bundle-Classpath", "Bundle-Copyright", "Bundle-Description", "Bundle-DocURL", "Bundle-License", "Bundle-ManifestVersion", "Bundle-Name", "Bundle-NativeCode", "Bundle-RequiredExecutionEnvironment", "Bundle-SymbolicName", "Bundle-Vendor", "Bundle-Version", "Caller-Allowable-Codebase", "Can-Redefine-Classes", "Can-Retransform-Classes", "Can-Set-Native-Method-Prefix", "Caplets", "Change", "Class-Path", "Codebase", "Corda-Platform-Version", "Corda-Release-Version", "Corda-Revision", "Corda-Vendor", "Cordapp-Contract-Licence", "Cordapp-Contract-Name", "Cordapp-Contract-Vendor", "Cordapp-Contract-Version", "Cordapp-Workflow-Licence", "Cordapp-Workflow-Name", "Cordapp-Workflow-Vendor", "Cordapp-Workflow-Version", "Created-By", "DSTAMP", "DynamicImport-Package", "Eclipse-BuddyPolicy", "Eclipse-LazyStart", "Embed-Dependency", "Export-Package", "Extension-Name", "Fragment-Host", "Gradle-Version", "Hibernate-JpaVersion", "Hibernate-VersionFamily", "Ignore-Package", "Implementation-Build", "Implementation-Build-Date", "Implementation-Title", "Implementation-URL", "Implementation-Url", "Implementation-Vendor", "Implementation-Vendor-Id", "Implementation-Version", "Import-Package", "Include-Resource", "JCabi-Build", "JCabi-Date", "JCabi-Version", "JVM-Args", "Java-Agents", "Java-Vendor", "Java-Version", "Kotlin-Runtime-Component", "Kotlin-Version", "Liquibase-Package", "Log4jReleaseKey", "Log4jReleaseManager", "Log4jReleaseVersion", "Main-Class", "Main-class", "Manifest-Version", "Min-Java-Version", "Min-Platform-Version", "Min-Update-Version", "Module-Email", "Module-Origin", "Module-Owner", "Module-Source", "Multi-Release", "Originally-Created-By", "Os-Arch", "Os-Name", "Os-Version", "Package", "Permissions", "Premain-Class", "Private-Package", "Probe-Provider-XML-File-Names", "Provide-Capability", "Require-Bundle", "Require-Capability", "SCM-Revision", "SCM-url", "Scm-Connection", "Scm-Revision", "Scm-Url", "Sealed", "Service-Component", "Specification-Title", "Specification-Vendor", "Specification-Version", "SwaggerUi-Version", "System-Properties", "TODAY", "TSTAMP", "Target-Platform-Version", "Time-Zone-Database-Version", "Tool", "Trusted-Library", "Version", "X-Compile-Source-JDK", "X-Compile-Target-JDK", "X-Git-Hash", "build-time", "implementation-version", "mode", "package", "service", "url"]

Error when moving an evolvable token

  • Corda OS 4.3-RC01
  • Tokens 1.1-RC01

Here's the sequence of events:

  1. Create EvolvableTokenType
  2. Issue a token of that type to a node
  3. Move part of that amount to a new node

I get the following error:

com.r3.corda.lib.tokens.selection.InsufficientBalanceException: Insufficient spendable states identified for 0.000001 TokenPointer(class xxx, defcb428-a1f6-4765-9241-1a9ee5f703b1) issued by xxx.	at com.r3.corda.lib.tokens.selection.database.selector.DatabaseTokenSelection.selectTokens(DatabaseTokenSelection.kt:140) ~[tokens-selection-1.1-RC01.jar:?]

As you can see from the picture below, I issued 10, the balance of the node is 10, I created an amount of 1 which I used in the move flow.

Capture

Feature request: decentralised interest rate application

This is a draft design document for interest rates support in the tokens SDK.

Overview

Some users want to apply interest rates to their tokens.

This feature can be used to implement different kinds of monetary policy. For instance, an unbacked token with a positive interest rate that decreases to zero over time could be used to implement a form of monetary distribution similar to what Satoshi implemented for Bitcoin, but without the special privileges awarded to miners. Such coins would just grow in your hands until the total monetary limit is reached.

More conventionally, commercial banks may use the feature to share investment returns with users, or even share investment failures with users by applying a negative interest rate. And central bank issued tokens may attempt to socially engineer particular outcomes, typically GDP growth, by forcing people to spend their savings or lose them. Charging negative interest is a more direct and thus more easily measured and understood mechanism than inflating the currency, which inherently creates distortions in the economy.

Problem statement. The tokens SDK does not implement interest rates. An oft-proposed approach is to periodically bring tokens back to the issuer for value adjustment. This creates problematic privacy, scaling, availability and incentive problems. In particular holders of tokens are not incentivised to return to the issuer if they'd face a negative interest rate, even if they're using tokens where they previously agreed to such negative rates e.g. because the token represents a share in an investment fund. We'd like a better approach.

Commentary. Negative interest rates have historically been seen as impossible or obviously absurd, due partly to lack of enforcement ability. They are deeply controversial and unpopular. We are not unaware of this unpopularity (in fact Switzerland has -0.75% rates today). But even in a world where everyone used Tokens SDK tokens as a replacement for cash, Corda is a general platform. An attempt to force people to use tokens with negative rates would result in people creating their own tokens, and building purely digital FX/OTC markets for them, as we've seen in the cryptocurrency world. Negative rates are most often talked about as a way to force people to spend money, given the apparent contemporary difficulty of creating inflation, thus boosting GDP. As GDP is the primary metric by which economists and politicians are judged this is seen as inherently good. But economic activity for the sake of gaming the measurement criteria of certain social classes is the fallacy of a planned economy. Policymakers who want to use them should consider campaigning for political leadership to be judged by other metrics instead. A focus on GDP growth at any cost will lead to either abandonment of CB managed currencies in favour of privately issued tokens e.g. Libra, or the totalitarianism required to avoid it.

Goals

  • Small extension of the existing code: demonstrate the cut lines of the feature, not implement full blown support.
  • No dependence on an issuer node, thus avoiding scaling bottlenecks.
  • Issuers should not get to see the chain of custody transactions (even if protected by enclaves or cryptography).
  • Incentive compatible: users should not be able to avoid negative rates if imposed.

Non-goals

  • Management tools, GUIs or other infrastructure to manage the setting of rates.
  • Support for very rapidly changing rates. We assume for scaling reasons that rates are adjusted only rarely, as today.
  • Solving dust limits.

Design

Design outline

The core idea is to make tokens self-inflating or deflating via the contract logic. Currently the smart contract enforces that during a payment the outputs sum to the value of the inputs. There's no requirement this be so, which is why the contract has to enforce it in the first place.

A new type of linear state can be defined which contains a list of interest rate changes over time (this is the source of the "no constant rate changes" non-goal). Only the issuer of the token may update this state. The rates state is included as a reference state into all transactions that spend the tokens, this is enforced by the token contract.

Each token state contains a timestamp of when the token last had interest applied.

The token contract then examines the timestamp window in the transaction header and takes the start of the time window (NOT the midpoint, as that'd allow arbitrary inflation). It then walks back through the history of rate changes in the ref state, from the tx timestamp until the "last applied" timestamp. It thus obtains a record of what rates were in force during the time this token was static, and can then apply the calculations to verify the final value.

Using tokens from other apps

The token state object should expose a utility method to do this calculation. This logic is of course used in the payment flows, which can invoke it to calculate the expected value during token movement. It should also be used by any other app that wishes to inspect the value of a token state and calculate its "true" value, e.g. if another app allows tokens to be used as reference states as a proof of solvency. Failure to use the interest-applied rate would be a critical bug in the other apps, so, as part of this feature, it may be desirable to make the "true" value of the token private and expose only a getter as a way to calculate the value of the token, however, this would probably be API incompatible. It's possible a new token type should be created, but, the details of that are left for the real design doc (this GitHub issue is only a starting point).

Calculating the monetary base

If the issuer wants to know how many tokens are in circulation at a given moment it can just apply the rate history to all issued tokens to arrive at how much would exist, if all tokens moved at that instant. From an economics perspective this should be sufficient as it's not the historical amount on the ledger that matters but rather how much is actually available to spend.

Time-varying balances in the API

The current Corda API doesn't directly expose any notion of balance. The Tokens SDK should expose such a notion but add support for querying "my expected balance at time T" which would use the new code on the state to apply the rates.

Dust limits

A negative rate erodes tokens such that their value trends to zero without ever actually hitting it.

At some point the value of a token is so low that it doesn't really make sense to store or work with it anymore. This is especially true if there are transaction fees of any sort. In the Bitcoin world we called this "dust" and it could be a significant problem. With time-varying transaction fees, the dust limit is itself variable.

Solving the problem of dust is a non-goal for three reasons:

  1. The obvious approach of letting an issuer set their own dust limit and then forcing erasure of any token states that fall below that value is wide open to hacking and errors destroying money incorrectly. It could also be used maliciously as another way to try and force people to spend their tokens, by progressively raising the limit.
  2. It's unclear how transaction fees in Corda will shake out, if at all. It very much depends on policies selected by token issuers, wallet developers and notary coalitions. The dust limit may in fact vary between users.
  3. Dust was a problem in Bitcoin primarily because of very high per-byte tx fees. If fees aren't levied per-byte or per-input, then the cost of aggregating lots of tiny outputs may be low or zero, meaning dust isn't really a problem unless a wallet itself runs out of funds.

Conclusion

This issue lays out a design for applying interest rates to tokens in a decentralised, privacy-preserving manner. Tokens never need to be returned to the issuer for value adjustment, yielding large scaling and availability benefits. Tokens representing shared investments may distribute the gains or losses in equally privacy preserving and decentralised manners.

With this power comes responsibility. Tokens that force people to spend them, in order to generate artificial activity for political/marketing reasons, can and should find themselves outcompeted in the market. Corda's transaction and multi-app interop features enable low trust discovery and OTC trading of tokens, and the cryptocurrency community has done many experiments with building truly decentralised trading venues. Such venues would be much easier to build with the facilities of the flow framework.

Unable to disable in-memory token selection if flow tests

Corda 4.3 OpenSource
Tokens SDK 1.1

Currently in-memory selection is enabled by default, and to disable it you need to add tokens-selection-1.1.conf under cordapps/config with the following:

stateSelection.inMemory.enabled=false
// You need to supply the below values even when disabling, 
// otherwise you'll get a warning.
stateSelection.inMemory.indexingStrategies: ["EXTERNAL_ID"]
stateSelection.inMemory.cacheSize=1024

The above worked fine for me when running nodes locally, but I wasn't able to achieve the same for flow tests.

  • Create config:
Map<String, String> selectionConfig = new LinkedHashMap<>();
selectionConfig.put("stateSelection.inMemory.enabled","false");
selectionConfig.put("stateSelection.inMemory.indexingStrategies", "[\"EXTERNAL_ID\"]");
selectionConfig.put("stateSelection.inMemory.cacheSize", "1024");
  • Supply config to cordapp:
TestCordapp.findCordapp("com.r3.corda.lib.tokens.selection").withConfig(selectionConfig)

When I run my test in debug mode, I noticed that InMemorySelectionConfig is not able to identify my keys even though they're there. Notice how exists() returns false even though the object config has that value:

Config

Allow additional transaction items

Does it make sense to modify the SDK flows in such a way as to allow additional transaction items? For example, consider custom contracts/states used on the road to issuance in some cordapp; wouldn't it be useful to have those updated within e.g. the IssueToken.Initiator's transaction by injecting the corresponding, custom input/output/command TX items?

Cannot deploy CorDapp with tokens SDK 1.0 and Corda 4.1

Running deployNodes gets an error because 'R3' doesn't have 2 letters:

* What went wrong:
Execution failed for task ':deployNodes'.
> Illegal input legal name 'R3'. Legal name must have at least two letters
   > Illegal input legal name 'R3'. Legal name must have at least two letters

RedeemFungibleTokens flow not working when passing observers

We are trying to implement Token SDK into our existing project. Issuance and Move commands are seem to be working fine. However, RedeemFungibleTokens fails when observers are passed to the flow. I replicated the problem with cordapp-template-kotlin TokenSDK branch.

The error is below:

OBSERVER NODE:

invocation_timestamp=2019-07-10T13:59:56.665Z, origin=O=PartyB, L=New York, C=US, session_id=dc0b167d-2ca1-41a3-a98e-2f6701e3ea6e, session_timestamp=2019-07-10T13:59:56.665Z, thread-id=224}
[WARN ] 2019-07-10T13:59:57,752Z [Node thread-1] interceptors.DumpHistoryOnErrorInterceptor.executeTransition - Flow [2f12da1e-014d-4d9f-b765-a7c877778a03] error [errorCode=scrdwz, moreInformationAt=https://errors.corda.net/OS/4.1/scrdwz] {fiber-id=10000001, flow-id=2f12da1e-014d-4d9f-b765-a7c877778a03, invocation_id=dc0b167d-2ca1-41a3-a98e-2f6701e3ea6e, invocation_timestamp=2019-07-10T13:59:56.665Z, origin=O=PartyB, L=New York, C=US, session_id=dc0b167d-2ca1-41a3-a98e-2f6701e3ea6e, session_timestamp=2019-07-10T13:59:56.665Z, thread-id=224}
java.lang.IllegalArgumentException: Payload invalid
at net.corda.core.internal.InternalUtils.checkPayloadIs(InternalUtils.kt:518) ~[corda-core-4.1.jar:?]
at net.corda.node.services.statemachine.FlowSessionImpl.receive(FlowSessionImpl.kt:67) ~[corda-node-4.1.jar:?]
at net.corda.node.services.statemachine.FlowSessionImpl.receive(FlowSessionImpl.kt:71) ~[corda-node-4.1.jar:?]
at net.corda.confidential.IdentitySyncFlow$Receive.call(IdentitySyncFlow.kt:113) ~[corda-confidential-identities-4.1.jar:?]
at net.corda.confidential.IdentitySyncFlow$Receive.call(IdentitySyncFlow.kt:84) ~[corda-confidential-identities-4.1.jar:?]
at net.corda.node.services.statemachine.FlowStateMachineImpl.subFlow(FlowStateMachineImpl.kt:329) ~[corda-node-4.1.jar:?]
at net.corda.core.flows.FlowLogic.subFlow(FlowLogic.kt:314) ~[corda-core-4.1.jar:?]
at com.r3.corda.lib.tokens.workflows.flows.redeem.RedeemTokensFlowHandler.call(RedeemTokensFlowHandler.kt:27) ~[?:?]
at com.r3.corda.lib.tokens.workflows.flows.redeem.RedeemTokensFlowHandler.call(RedeemTokensFlowHandler.kt:22) ~[?:?]
at net.corda.node.services.statemachine.FlowStateMachineImpl.subFlow(FlowStateMachineImpl.kt:329) ~[corda-node-4.1.jar:?]
at net.corda.core.flows.FlowLogic.subFlow(FlowLogic.kt:314) ~[corda-core-4.1.jar:?]
at com.r3.corda.lib.tokens.workflows.flows.rpc.RedeemFungibleTokensHandler.call(RedeemTokens.kt:35) ~[?:?]
at com.r3.corda.lib.tokens.workflows.flows.rpc.RedeemFungibleTokensHandler.call(RedeemTokens.kt:33) ~[?:?]
at net.corda.node.services.statemachine.FlowStateMachineImpl.run(FlowStateMachineImpl.kt:269) ~[corda-node-4.1.jar:?]
at net.corda.node.services.statemachine.FlowStateMachineImpl.run(FlowStateMachineImpl.kt:45) ~[corda-node-4.1.jar:?]
at co.paralleluniverse.fibers.Fiber.run1(Fiber.java:1092) ~[quasar-core-0.7.10-jdk8.jar:0.7.10]
at co.paralleluniverse.fibers.Fiber.exec(Fiber.java:788) ~[quasar-core-0.7.10-jdk8.jar:0.7.10]
at co.paralleluniverse.fibers.RunnableFiberTask.doExec(RunnableFiberTask.java:100) ~[quasar-core-0.7.10-jdk8.jar:0.7.10]
at co.paralleluniverse.fibers.RunnableFiberTask.run(RunnableFiberTask.java:91) ~[quasar-core-0.7.10-jdk8.jar:0.7.10]
at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511) ~[?:1.8.0_212]
at java.util.concurrent.FutureTask.run(FutureTask.java:266) ~[?:1.8.0_212]
at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.access$201(ScheduledThreadPoolExecutor.java:180) ~[?:1.8.0_212]
at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:293) ~[?:1.8.0_212]
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149) ~[?:1.8.0_212]
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624) ~[?:1.8.0_212]
at net.corda.node.utilities.AffinityExecutor$ServiceAffinityExecutor$1$thread$1.run(AffinityExecutor.kt:63) ~[corda-node-4.1.jar:?]
Caused by: java.io.NotSerializableException: Described type with descriptor net.corda:vlc3i8lJnO7K1i2g0g0+aA== was expected to be of type interface java.util.List but was class com.r3.corda.lib.tokens.workflows.internal.flows.finality.TransactionRole
at net.corda.serialization.internal.amqp.DeserializationInput.des(DeserializationInput.kt:102) ~[corda-serialization-4.1.jar:?]
at net.corda.serialization.internal.amqp.DeserializationInput.deserialize(DeserializationInput.kt:119) ~[corda-serialization-4.1.jar:?]
at net.corda.serialization.internal.amqp.AbstractAMQPSerializationScheme.deserialize(AMQPSerializationScheme.kt:225) ~[corda-serialization-4.1.jar:?]
at net.corda.serialization.internal.SerializationFactoryImpl$deserialize$1$1.invoke(SerializationScheme.kt:105) ~[corda-serialization-4.1.jar:?]
at net.corda.core.serialization.SerializationFactory.withCurrentContext(SerializationAPI.kt:71) ~[corda-core-4.1.jar:?]
at net.corda.serialization.internal.SerializationFactoryImpl$deserialize$1.invoke(SerializationScheme.kt:105) ~[corda-serialization-4.1.jar:?]
at net.corda.serialization.internal.SerializationFactoryImpl$deserialize$1.invoke(SerializationScheme.kt:73) ~[corda-serialization-4.1.jar:?]
at net.corda.core.serialization.SerializationFactory.asCurrent(SerializationAPI.kt:85) ~[corda-core-4.1.jar:?]
at net.corda.serialization.internal.SerializationFactoryImpl.deserialize(SerializationScheme.kt:105) ~[corda-serialization-4.1.jar:?]
at net.corda.core.internal.InternalUtils.checkPayloadIs(InternalUtils.kt:516) ~[corda-core-4.1.jar:?]
... 25 more

PartyB Node from which redemption is being requested:
{actor_id=internalShell, actor_owning_identity=O=PartyB, L=New York, C=US, actor_store_id=NODE_CONFIG, fiber-id=10000002, flow-id=68dceb19-d589-4eea-a0dd-1a9802b2cb19, invocation_id=7fce675c-c55d-4fff-8550-c469f8ea1f8a, invocation_timestamp=2019-07-10T13:59:55.269Z, origin=internalShell, session_id=5a98a18e-6aa4-4eb7-b3db-2a2ca841c2ec, session_timestamp=2019-07-10T13:59:54.977Z, thread-id=224, tx_id=C37D91942BCA1AC7F991DB17920FD35F26F2426721FCFCBAB7257B76F6BBA3CD}
[WARN ] 2019-07-10T13:59:58,272Z [Node thread-1] interceptors.DumpHistoryOnErrorInterceptor.executeTransition - Flow [68dceb19-d589-4eea-a0dd-1a9802b2cb19] error [errorCode=1sprsib, moreInformationAt=https://errors.corda.net/OS/4.1/1sprsib] {actor_id=internalShell, actor_owning_identity=O=PartyB, L=New York, C=US, actor_store_id=NODE_CONFIG, fiber-id=10000002, flow-id=68dceb19-d589-4eea-a0dd-1a9802b2cb19, invocation_id=7fce675c-c55d-4fff-8550-c469f8ea1f8a, invocation_timestamp=2019-07-10T13:59:55.269Z, origin=internalShell, session_id=5a98a18e-6aa4-4eb7-b3db-2a2ca841c2ec, session_timestamp=2019-07-10T13:59:54.977Z, thread-id=224, tx_id=C37D91942BCA1AC7F991DB17920FD35F26F2426721FCFCBAB7257B76F6BBA3CD}
net.corda.core.flows.UnexpectedFlowEndException: O=Observer, L=New York, C=US has finished prematurely and we're trying to send them the finalised transaction. Did they forget to call ReceiveFinalityFlow? (Counter-flow errored)

Withdraw flow:

class WithdrawToken(val currency: String, val amount: Long, val issuer: Party, val observer: Party) : FlowLogic<SignedTransaction>() { override val progressTracker = ProgressTracker() @Suspendable override fun call(): SignedTransaction { val token = FiatCurrency.getInstance(currency) // Starts a new flow session. return subFlow(RedeemFungibleTokens(amount of token, issuer, listOf(observer))) } }

Should FungibleTokenBuilder and NonFungibleTokenBuilder heldBy function receive a Party ?

This is a small thing I noticed with the new FungibleTokenBuilder and NonFungibleTokenBuilder classes. I'm not sure if it matters but I think it would cause some issues if you wanted to use them with AnonymousParty?

The holder parameter for FungibleToken and NonFungibleToken is AbstractParty:

open class FungibleToken @JvmOverloads constructor(
        override val amount: Amount<IssuedTokenType>,
        override val holder: AbstractParty,
        override val tokenTypeJarHash: SecureHash? = amount.token.tokenType.getAttachmentIdForGenericParam()
) : FungibleState<IssuedTokenType>, AbstractToken, QueryableState {

Whereas the heldBy function in the new builders is Party:

    fun heldBy(party: Party): FungibleTokenBuilder = this.apply {
        this.holder = party
    }

Is TransactionUtilitiesKt removed from token sdk ?

I have received all the dependencies related to token-sdk and here I am attaching image for same
Screenshot 2019-11-27 at 3 52 28 PM

What I want to do?
I want to import com.r3.corda.lib.tokens.contracts.utilities.TransactionUtilities for below code
val fungibleToken = FungibleToken(amount,holder,TransactionUtilitiesKt.getAttachmentIdForGenericParam(tokenPointer))

Note: I'm doing code in kotlin

What happened ?
It says unresolved reference at TransactionUtilities So, The TransactionUtilities removed in the latest updates? if yes suggest any way to call FungibleToken.

Any suggestions/help appreciated.

Error with token sdk dependencies when deploying nodes in the kotlin cordapp template

I'm geting the following error when running deploy nodes in the kotlin cordapp template using the token template branch. I followed the instructions in this README

:contracts:compileKotlin FAILED

FAILURE: Build failed with an exception.

  • What went wrong:
    Execution failed for task ':contracts:compileKotlin'.

Could not resolve all files for configuration ':contracts:compileClasspath'.
Could not find com.r3.corda.sdk.token:token-sdk-contract:0.1.
Searched in the following locations:
https://jcenter.bintray.com/com/r3/corda/sdk/token/token-sdk-contract/0.1/token-sdk-contract-0.1.pom
https://jcenter.bintray.com/com/r3/corda/sdk/token/token-sdk-contract/0.1/token-sdk-contract-0.1.jar
https://repo.maven.apache.org/maven2/com/r3/corda/sdk/token/token-sdk-contract/0.1/token-sdk-contract-0.1.pom
https://repo.maven.apache.org/maven2/com/r3/corda/sdk/token/token-sdk-contract/0.1/token-sdk-contract-0.1.jar
https://ci-artifactory.corda.r3cev.com/artifactory/corda/com/r3/corda/sdk/token/token-sdk-contract/0.1/token-sdk-contract-0.1.pom
https://ci-artifactory.corda.r3cev.com/artifactory/corda/com/r3/corda/sdk/token/token-sdk-contract/0.1/token-sdk-contract-0.1.jar
https://ci-artifactory.corda.r3cev.com/artifactory/corda-dev/com/r3/corda/sdk/token/token-sdk-contract/0.1/token-sdk-contract-0.1.pom
https://ci-artifactory.corda.r3cev.com/artifactory/corda-dev/com/r3/corda/sdk/token/token-sdk-contract/0.1/token-sdk-contract-0.1.jar
https://jitpack.io/com/r3/corda/sdk/token/token-sdk-contract/0.1/token-sdk-contract-0.1.pom
https://jitpack.io/com/r3/corda/sdk/token/token-sdk-contract/0.1/token-sdk-contract-0.1.jar
file:/Users/estudiante/.m2/repository/com/r3/corda/sdk/token/token-sdk-contract/0.1/token-sdk-contract-0.1.pom
file:/Users/estudiante/.m2/repository/com/r3/corda/sdk/token/token-sdk-contract/0.1/token-sdk-contract-0.1.jar
Required by:
project :contracts
Could not find com.r3.corda.sdk.token.modules:token-sdk-money:0.1.
Searched in the following locations:
https://jcenter.bintray.com/com/r3/corda/sdk/token/modules/token-sdk-money/0.1/token-sdk-money-0.1.pom
https://jcenter.bintray.com/com/r3/corda/sdk/token/modules/token-sdk-money/0.1/token-sdk-money-0.1.jar
https://repo.maven.apache.org/maven2/com/r3/corda/sdk/token/modules/token-sdk-money/0.1/token-sdk-money-0.1.pom
https://repo.maven.apache.org/maven2/com/r3/corda/sdk/token/modules/token-sdk-money/0.1/token-sdk-money-0.1.jar
https://ci-artifactory.corda.r3cev.com/artifactory/corda/com/r3/corda/sdk/token/modules/token-sdk-money/0.1/token-sdk-money-0.1.pom
https://ci-artifactory.corda.r3cev.com/artifactory/corda/com/r3/corda/sdk/token/modules/token-sdk-money/0.1/token-sdk-money-0.1.jar
https://ci-artifactory.corda.r3cev.com/artifactory/corda-dev/com/r3/corda/sdk/token/modules/token-sdk-money/0.1/token-sdk-money-0.1.pom
https://ci-artifactory.corda.r3cev.com/artifactory/corda-dev/com/r3/corda/sdk/token/modules/token-sdk-money/0.1/token-sdk-money-0.1.jar
https://jitpack.io/com/r3/corda/sdk/token/modules/token-sdk-money/0.1/token-sdk-money-0.1.pom
https://jitpack.io/com/r3/corda/sdk/token/modules/token-sdk-money/0.1/token-sdk-money-0.1.jar
file:/Users/estudiante/.m2/repository/com/r3/corda/sdk/token/modules/token-sdk-money/0.1/token-sdk-money-0.1.pom
file:/Users/estudiante/.m2/repository/com/r3/corda/sdk/token/modules/token-sdk-money/0.1/token-sdk-money-0.1.jar
Required by:
project :contracts

AbstractTokenContract allows arbitrary command

In the AbstractTokenContract, transaction verification functions are called in the following order:
verify() -> dispatchOnCommand() -> verifyIssue(), verifyMove(), or verifyRedeem()
In the function of dispatchOnCommand(), it assumes the command is one of IssueTokenCommand, MoveTokenCommand and RedeemTokenCommand

when (commands.first().value) {
	//verify the type jar presence and correctness
	// Issuances should only contain one issue command.
	is IssueTokenCommand -> verifyIssue(commands.single(), inputs, outputs, attachments, references)
	// Moves may contain more than one move command.
	is MoveTokenCommand -> verifyMove(commands, inputs, outputs, attachments, references)
	// Redeems must only contain one redeem command.
	is RedeemTokenCommand -> verifyRedeem(commands.single(), inputs, outputs, attachments, references)
}

If someone makes a new command, and use it with the FungibleTokenContract, then the contract will verify nothing since it does not know the command.
Shouldn't the above code throw exception at the end when the command is unknown?

Make TokenSDK support high-precision assets

As the the worlds of traditional and crypto assets gradually converge, we need to be prepared for firms (and notably large institutional firms) looking to trade a variety of asset classes including those that require high-precision amounts. These classically include BTC, Ripple, ETH and also the vast majority of Ethereum tokens. TokenSDK, being steeped in the Corda Amount, uses Longs to represent amounts (using a divisor) which are insufficient to represent the aforementioned asset types. This request is for TokenSDK to formally support BigDecimal amounts.

DatabaseTokenSelection.selectTokens doesn't see newly issued tokens

Corda: CE 4.3
Tokens: 1.1-RC01

My design is as following:

  1. I have 2 nodes: Mint and Wallet.
  2. Mint creates new tokens (calls IssueTokens to itself).
  3. Wallet has user accounts (Account library).
  4. Mint has a flow to issue tokens to accounts on Wallet (calls MoveFungibleTokens).
  5. Mint doesn't create a circulating supply then use it, meaning I don't create 1000,000 tokens then use them, instead; the Mint mints as you go.
  6. If the Mint has balance, it will just transfer the required quantity to the account on Wallet.
  7. If the Mint doesn't have enough balance, it will mint new tokens (i.e. issue to itself) then move the required amount to Wallet.
  8. Please note that for better performance I mint extra tokens, meaning if the Mint is short of 5 tokens, I mint 100; so next time the Mint wants to issue to an account; it will most probably have balance. Anyway...

The problem is in the following flow test scenario:

  1. The Mint node has balance of 10.
  2. I call the issue flow to issue 90 tokens to an account.
  3. The Mint will mint 100 new tokens (issue to itself).
  4. The Mint will transfer 90 tokens to the account on Wallet.
  5. The Mint's new balance is 10 + 100 - 90 = 20.

The problem is in step 4, I ran the test in debug mode and reached DatabaseTokenSelection.selectTokens and when it queries the vault, it only sees 10 tokens:

image

Even though when I query the vault, I can see the 110 tokens (i.e. initial balance of 10 + newly minted 100). I have a function that does that before and after minting, so my flow steps were:

  1. Check Mint balance -> returned <false, Mint balance: 10> (false, as in it doesn't have enough balance)
  2. Mint new tokens
  3. Check Mint balance -> returned <true, Mint balance: 110> (true because now it has enough balance)
  4. Call MoveFungibleTokens which fails because again DatabaseTokenSelection.selectTokens only sees the initial 10 tokens balance which is not enough to transfer the requested 90.

image

Error Redeeming self-issued Fungible Tokens

Operating System: Windows 10
Corda: 4.3
tokens_release_version = '1.1-RC05-PRESIGN'
Testing with a MockNetwork

I have been testing token-sdk and I stumbled into an error. It’s probably something I am doing wrong but I thought I would post it here just in case.

I’m getting the error when a Party issues FungibleTokens to itself and then redeems them using initiating flow RedeemFungibleTokens:

return subFlow(new RedeemFungibleTokens(amount, issuer, observers));

If I examine the vault the redeem seems to work as the FungibleTokens are consumed. All my other redeems work where the Tokens are directly issued to a second party and then redeemed. Or if the issuer issues Fungible Tokens to themselves, moves the tokens to a second Party and then that Party redeems them. I get the same error with our without observers.

I am going to test the inline redeem next : RedeemFungibleTokensFlow()

Let me know if I can provide any other information.

Here is the error:

[INFO] 16:28:56,442 [Mock network] corda.flow. - Flow raised an error: Tried to access ended session SessionId(toLong=-5509191397927053834) with empty buffer. Sending it to flow hospital to be triaged. {fiber-id=10000017, flow-id=ab81366b-47b7-47e1-b30c-704143e33af7, invocation_id=d2fdc33a-f1b7-4f0a-a3d6-dd0d2fb7c8b1, invocation_timestamp=2019-12-03T23:28:55.424Z, origin=O=Federal Reserve, L=New York City, C=US, session_id=d2fdc33a-f1b7-4f0a-a3d6-dd0d2fb7c8b1, session_timestamp=2019-12-03T23:28:55.424Z, thread-id=829}

[INFO] 16:28:56,445 [Mock network] statemachine.StaffedFlowHospital. - Flow [ab81366b-47b7-47e1-b30c-704143e33af7] admitted to hospital in state StateMachineState(checkpoint=Checkpoint(invocationContext=InvocationContext(origin=Peer(party=O=Federal Reserve, L=New York City, C=US), trace=Trace(invocationId=d2fdc33a-f1b7-4f0a-a3d6-dd0d2fb7c8b1, timestamp: 2019-12-03T23:28:55.424Z, entityType: Invocation, sessionId=d2fdc33a-f1b7-4f0a-a3d6-dd0d2fb7c8b1, timestamp: 2019-12-03T23:28:55.424Z, entityType: Session), actor=null, externalTrace=null, impersonatedActor=null), ourIdentity=O=Federal Reserve, L=New York City, C=US, sessions={SessionId(toLong=-5509191397927053834)=Initiated(peerParty=O=Federal Reserve, L=New York City, C=US, peerFlowInfo=FlowInfo(flowVersion=1, appName=tokens-workflows-1.1-RC05-PRESIGN), receivedMessages=[], initiatedState=Ended, errors=[], deduplicationSeed=D-6749170431553071374-6281469155197028627)}, subFlowStack=[Inlined(flowClass=class com.r3.corda.lib.tokens.workflows.flows.rpc.RedeemFungibleTokensHandler, subFlowVersion=CorDappFlow(platformVersion=5, corDappName=tokens-workflows-1.1-RC05-PRESIGN, corDappHash=1E6A18A16B476D6898C230A44392385A326754A023F6304484CC7115E6C5F16B), isEnabledTimedFlow=false)], flowState=Started(flowIORequest=Receive(sessions=[FlowSessionImpl(destination=O=Federal Reserve, L=New York City, C=US, sourceSessionId=SessionId(toLong=-5509191397927053834))]), frozenFiber=4FB0427091DDBFE448DED701C5C01B9F8F5CD6C08BC9E0241D295838A217E360), errorState=Clean, numberOfSuspends=5), flowLogic=com.r3.corda.lib.tokens.workflows.flows.rpc.RedeemFungibleTokensHandler@4f79df95, pendingDeduplicationHandlers=[net.corda.testing.node.internal.MockNodeMessagingService$InMemoryDeduplicationHandler@77eae423], isFlowResumed=true, isTransactionTracked=false, isAnyCheckpointPersisted=true, isStartIdempotent=false, isRemoved=false, senderUUID=caea3be1-72d0-41e6-ae62-e39b141ea180) {fiber-id=10000017, flow-id=ab81366b-47b7-47e1-b30c-704143e33af7, invocation_id=d2fdc33a-f1b7-4f0a-a3d6-dd0d2fb7c8b1, invocation_timestamp=2019-12-03T23:28:55.424Z, origin=O=Federal Reserve, L=New York City, C=US, session_id=d2fdc33a-f1b7-4f0a-a3d6-dd0d2fb7c8b1, session_timestamp=2019-12-03T23:28:55.424Z, thread-id=829}

[INFO] 16:28:56,448 [Mock network] statemachine.StaffedFlowHospital. - Error 1 of 1: {fiber-id=10000017, flow-id=ab81366b-47b7-47e1-b30c-704143e33af7, invocation_id=d2fdc33a-f1b7-4f0a-a3d6-dd0d2fb7c8b1, invocation_timestamp=2019-12-03T23:28:55.424Z, origin=O=Federal Reserve, L=New York City, C=US, session_id=d2fdc33a-f1b7-4f0a-a3d6-dd0d2fb7c8b1, session_timestamp=2019-12-03T23:28:55.424Z, thread-id=829}

net.corda.core.flows.UnexpectedFlowEndException: Tried to access ended session SessionId(toLong=-5509191397927053834) with empty buffer

Agent artifact missing workflows dependency.

Our original deployment consisted of three separate Jars for Agent node.
payments-contracts
payments-workflows
payments-agent

Currently we are not providing payments-workflows, it is NOT included in Agent Jar currently. We can switch the build.gradle from cordaCompile to compile to reduce the number of artifacts and have it included.

Bug raised during test when deployNodes would not resolve required classes after removing payments-cordapp from nodeDefaults; as payments-cordapp should not be deployed on agent, but this jar DID have payments-workflows compiled in.

LocalTokenSelector selects redeemed tokens

Version tested:
Corda 4.3
TokenSDK 1.1

Steps to reproduce:

  1. Issue fungible tokens
  2. Redeem the tokens you just issued
  3. Select tokens using local token selector (this should fail as balance is 0 but doesn't)

Cause:
The vault observable used for local selection VaultWatcherService:98 uses a criteria with StateStatus.UNCONSUMED. This causes updates with only consumption events to be missed. This is highlighted in CORDA-2734

RedeemFungibleToken issue

Hi,
I have created 2 accounts in node A.

I have issued 70 USD to both accounts from node A.

However when I try to redeem token from first account (eg : 5 tokens) by explicitly specifying change holder attribute , redemption works the first time, however tokenHolder for remaining 65 units is changed to node A

Because of this redemption fails the second time as it explicitly checks for tokens held by the account.

Can somebody please explain what is going on in the above scenario? Is there anyway to mitigate this error and ensure that the tokens are indeed deducted from the expected accounts.

Thanks in advance

Update observer vaults in EvolvableToken create/update flows

We have use cases where a third party needs to be aware of an EvolvableToken as the initiator of a process without having previously participated in transactions that contain it. Up to now we were hijacking EvolvableToken#participants to update such a party's vault when creating/updating evolvable tokens but this is essentially a hack; it would be preferable to properly use observers in CreateEvolvableTokensFlow and UpdateEvolvableTokensFlow via ObserverAwareFinalityFlow and update observer vaults with relaxed relevance without requiring such a party to sign the create/update transaction.

There is a token group with no assigned command

Hi All,

We had an issue today with 1.0 t-sdk. Thanks for all the help debugging. The conclusion seems to be that we called addMoveToken twice for tokens that have the same grouping, this pulls in two commands and then we blow up later with the following exception:

[WARN ] 2019-07-16T12:42:00,158Z [flow-worker] interceptors.DumpHistoryOnErrorInterceptor.executeTransition - Flow [04ff054d-19b7-4aca-b147-c736a66ce397] error [errorCode=x4riem, moreInformationAt=https://errors.corda.net/ENT/4.0/x4riem] {fiber-id=10000005, flow-id=04ff054d-19b7-4aca-b147-c736a66ce397, invocation_id=7e0e9204-a097-44dd-a075-1df8725c00a7, invocation_timestamp=2019-07-16T12:41:56.709Z, origin=com.sdx.token.db.size.DubiousService, session_id=7e0e9204-a097-44dd-a075-1df8725c00a7, session_timestamp=2019-07-16T12:41:56.709Z, thread-id=305, tx_id=6184FB49C9BD1A4C3DD4BD04DDE2AB8C37E474F3353B8FFA6843D3774492E6AD}
net.corda.core.contracts.TransactionVerificationException$ContractRejection: Contract verification failed: There is a token group with no assigned command!, contract: com.r3.corda.lib.tokens.contracts.FungibleTokenContract, transaction: 6184FB49C9BD1A4C3DD4BD04DDE2AB8C37E474F3353B8FFA6843D3774492E6AD
        at net.corda.core.internal.Verifier.verifyContracts(TransactionVerifierServiceInternal.kt:380) ~[corda-core-4.0.jar:?]
        at net.corda.core.internal.Verifier.verify(TransactionVerifierServiceInternal.kt:71) ~[corda-core-4.0.jar:?]
        at net.corda.core.transactions.LedgerTransaction.verify(LedgerTransaction.kt:134) ~[corda-core-4.0.jar:?]
        at net.corda.core.flows.FinalityFlow.verifyTx(FinalityFlow.kt:232) ~[corda-core-4.0.jar:?]
        at net.corda.core.flows.FinalityFlow.call(FinalityFlow.kt:133) ~[corda-core-4.0.jar:?]
        at net.corda.core.flows.FinalityFlow.call(FinalityFlow.kt:39) ~[corda-core-4.0.jar:?]
        at net.corda.node.services.statemachine.FlowStateMachineImpl.subFlow(FlowStateMachineImpl.kt:303) ~[corda-node-4.0.jar:?]
        at net.corda.core.flows.FlowLogic.subFlow(FlowLogic.kt:314) ~[corda-core-4.0.jar:?]
        at com.r3.corda.lib.tokens.workflows.internal.flows.finality.ObserverAwareFinalityFlow.call(ObserverAwareFinalityFlow.kt:75) ~[?:?]
        at com.r3.corda.lib.tokens.workflows.internal.flows.finality.ObserverAwareFinalityFlow.call(ObserverAwareFinalityFlow.kt:35) ~[?:?]
        at net.corda.node.services.statemachine.FlowStateMachineImpl.subFlow(FlowStateMachineImpl.kt:303) ~[corda-node-4.0.jar:?]
        at net.corda.core.flows.FlowLogic.subFlow(FlowLogic.kt:314) ~[corda-core-4.0.jar:?]
        at com.blah.token.db.size.TransferSpecificChfTo.call(DbSizeFlows.kt:193) ~[?:?]
        at com.blah.token.db.size.TransferSpecificChfTo.call(DbSizeFlows.kt:156) ~[?:?]
        at net.corda.node.services.statemachine.FlowStateMachineImpl.run(FlowStateMachineImpl.kt:243) ~[corda-node-4.0.jar:?]
        at net.corda.node.services.statemachine.FlowStateMachineImpl.run(FlowStateMachineImpl.kt:45) ~[corda-node-4.0.jar:?]
        at co.paralleluniverse.fibers.Fiber.run1(Fiber.java:1092) ~[quasar-core-0.7.11_r3-jdk8.jar:0.7.11_r3]
        at co.paralleluniverse.fibers.Fiber.exec(Fiber.java:788) ~[quasar-core-0.7.11_r3-jdk8.jar:0.7.11_r3]
        at co.paralleluniverse.fibers.RunnableFiberTask.doExec(RunnableFiberTask.java:100) ~[quasar-core-0.7.11_r3-jdk8.jar:0.7.11_r3]
        at co.paralleluniverse.fibers.RunnableFiberTask.run(RunnableFiberTask.java:91) ~[quasar-core-0.7.11_r3-jdk8.jar:0.7.11_r3]
        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149) ~[?:1.8.0_201]
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624) ~[?:1.8.0_201]
        at io.netty.util.concurrent.FastThreadLocalRunnable.run(FastThreadLocalRunnable.java:30) ~[netty-common-4.1.29.Final.jar:4.1.29.Final]
        at java.lang.Thread.run(Thread.java:748) [?:1.8.0_201]
Caused by: java.lang.IllegalArgumentException: There is a token group with no assigned command!
        at com.r3.corda.lib.tokens.contracts.AbstractTokenContract.verify(AbstractTokenContract.kt:97) ~[?:?]
        at net.corda.core.internal.Verifier.verifyContracts(TransactionVerifierServiceInternal.kt:377) ~[corda-core-4.0.jar:?]
        ... 23 more

Thanks :-)

Inconsistent node balance with same API call

Corda CE = 4.3
Tokens = 1.1-RC01

  • I have a REST API that queries my Mint node and returns its balance (all the tokens on my Mint node are held by the Mint).
  • This API returns different results when ran multiple times consequently (I use Postman; several times within 10 minutes or so and it randomly returns a different balance) .
  • I don't run any code between those calls (i.e. no issue, transfer, or redeem commands).

Below is my code:

public Map<String, BigDecimal> getNodeBalance(@NotBlank String myTokenTypeId) {
	// Latest version of my EvolvablableTokenType.
	EvolvableMyTokenType myTokenType = MyTokenUtils.getLatestMyTokenType(proxy, myTokenTypeId);
	// Only tokens held by the Mint.
	QueryCriteria queryCriteria = QueryUtilitiesKt.heldTokenAmountCriteria(
			myTokenType.toPointer(myTokenType.getClass()),
			proxy.nodeInfo().getLegalIdentities().get(0));

	// Based off the code from Corda documentation (API: Vault Query).
	int pageNumber = DEFAULT_PAGE_NUM;
	final int pageSize = 200;
	long totalResults;
	long totalBalance = 0;
	do {
		PageSpecification pageSpec = new PageSpecification(pageNumber, pageSize);
		Vault.Page<FungibleToken> results = proxy.vaultQueryByWithPagingSpec(FungibleToken.class,
				queryCriteria, pageSpec);
		totalResults = results.getTotalStatesAvailable();
		if (totalResults == 0)
			return Collections.singletonMap("Node Balance", new BigDecimal(0));
		List<StateAndRef<FungibleToken>> pageMyTokens = results.getStates();
		// Is it possible the below line is behaving randomly?
		long pageBalance = pageMyTokens.stream()
				.mapToLong(t -> t.getState().getData().getAmount().getQuantity()).sum();
		totalBalance += pageBalance;
		pageNumber++;
	}
	while ((pageSize * (pageNumber - 1) <= totalResults));

	BigDecimal bigTotalBalance = new BigDecimal(totalBalance);
	// MyToken has 6 fraction digits; meaning 1000,000 = one MyToken.
	BigDecimal fractions = new BigDecimal(Math.pow(10, myTokenType.getFractionDigits()));
	BigDecimal nodeBalance = bigTotalBalance.divide(fractions);
	return Collections.singletonMap("Node Balance", nodeBalance);
}

I ran the webserver with remote debug and monitored the values of pageBalance and totalBalance. Notice how on the 5th page the returned results are different!!!

		Calling API	Calling same API again
Page balance: 	197727787	
Total so far:	197727787

Page balance:	200000000
Total so far:	397727787

Page balance:	200000000
Total so far:	597727787

Page balance:	200000000
Total so far:	797727787

Page balance:	62727787	65000000
Total so far:	860455574	862727787

Btw, the correct balance is the second API call (862727787); I use the below query in my pgAdmin:

select sum(amount)
from fungible_token 
-- Holder is Mint node
where holder = 'OU=XXX, O=XXX, L=London, C=GB'
and (transaction_id, output_index) 
in (
select transaction_id, output_index 
	from vault_states 
	-- Only tokens
	where contract_state_class_name = 'com.r3.corda.lib.tokens.contracts.states.FungibleToken' 
	-- Only unconsumed
	and state_status = 0
);

Regardless of which returned number is the correct balance; how is it that the same code is returning different results?

QueryUtilities.heldTokenAmountCriteria doesn't return correct balances when used with accounts.

  • Corda OS 4.3-RC01
  • Tokens 1.1-RCO01
  • Accounts 1.0-RC04
  • Confidential Identities 1.0-RC03

I'm trying to achieve the following:

  1. Create 2 accounts on the same node.
  2. Issue tokens to both accounts.
  3. Get the balance of each account.

I added the below test inside AnotherTest.kt which is part of the Accounts Library under examples \ tokens-integration-test.
If you run the test you will see that using heldTokenAmountCriteria doesn't return the balance of a certain account; instead it returns the balance of the entire node:

@Test
fun `Issue tokens to 2 accounts on the same node`() {
	driver(driverParameters) {
		val (nodeA, nodeB, nodeC, nodeI) = nodeParams.map { params -> startNode(params) }.transpose().getOrThrow()
		log.info("All nodes started up.")

		log.info("Creating 2 accounts on node A.")
		val createAccount1OnA = nodeA.rpc.startFlow(::CreateAccount, "TestAccount1A").returnValue.getOrThrow()
		val createAccount2OnA = nodeA.rpc.startFlow(::CreateAccount, "TestAccount2A").returnValue.getOrThrow()

		log.info("Creating confidential identities for both accounts.")
		val account1AAnonymous = nodeI.rpc.startFlow(::RequestKeyForAccount, createAccount1OnA.state.data).returnValue.getOrThrow()
		val account2AAnonymous = nodeI.rpc.startFlow(::RequestKeyForAccount, createAccount2OnA.state.data).returnValue.getOrThrow()

		log.info("Node I issues tokens to both accounts in node A.")
		val tokens1 = 55 of GBP issuedBy nodeI.legalIdentity() heldBy account1AAnonymous
		val issuance1Result = nodeI.rpc.startFlow(::IssueTokens, listOf(tokens1), emptyList()).returnValue.getOrThrow()
		val tokens2 = 35 of GBP issuedBy nodeI.legalIdentity() heldBy account2AAnonymous
		val issuance2Result = nodeI.rpc.startFlow(::IssueTokens, listOf(tokens2), emptyList()).returnValue.getOrThrow()

		log.info("Check balance of account1.")
		val criteria1 = heldTokenAmountCriteria(GBP, account1AAnonymous)
		val results1 = nodeA.rpc.vaultQueryBy<FungibleToken>(criteria1).states
		val acc1Bal = results1.sumByLong { t -> t.state.data.amount.quantity }
		assertEquals(Amount.fromDecimal(BigDecimal.valueOf(55), GBP).quantity, acc1Bal)

		log.info("Check balance of account2.")
		val criteria2 = heldTokenAmountCriteria(GBP, account2AAnonymous)
		val results2 = nodeA.rpc.vaultQueryBy<FungibleToken>(criteria2).states
		val acc2Bal = results2.sumByLong { t -> t.state.data.amount.quantity }
		assertEquals(Amount.fromDecimal(BigDecimal.valueOf(35), GBP).quantity, acc2Bal)
	}
}

Getting incompatible return type error when extending FungibleToken in Java

There is a question asked long time ago:
https://stackoverflow.com/questions/57650475/error-when-extending-fungibletoken-supportedschemas-in-queryablestate-clashes

As shown in the question, when extending FungibleToken, it will get the error of incompatible return type. This only happens when writing in Java. Kotlin works just fine.
This could be because the supportedSchemas() in the FungibleToken does not specify its return type.

That's to say, if we change the supportedSchemas() method in the FungibleToken from
override fun supportedSchemas() = listOf(FungibleTokenSchemaV1)
to
override fun supportedSchemas() : Iterable<MappedSchema> = listOf(FungibleTokenSchemaV1)
Then the error will disappear.

Issues with master

Master has a failed test, plus needs version updates to Corda 4.0 and gradle plugins 4.0.41

manos@sobol:~/git/token-sdk$ ./gradlew  build install

> Task :workflow:test 

com.r3.corda.sdk.token.workflow.TokenFlowTests > create evolvable token, then issue and move FAILED

The failed test stacktrace is

java.lang.IllegalStateException: The LinearState with ID 0dcf21fb-7fb1-48ce-b894-c25a523f6f2f is unknown to this node or it has been exited from the ledger.
	at net.corda.core.contracts.LinearPointer.resolve(StatePointer.kt:113)
	at net.corda.core.transactions.TransactionBuilder.resolveStatePointers(TransactionBuilder.kt:530)
	at net.corda.core.transactions.TransactionBuilder.addInputState(TransactionBuilder.kt:584)
	at com.r3.corda.sdk.token.workflow.selection.TokenSelection.generateMove(TokenSelection.kt:213)
	at com.r3.corda.sdk.token.workflow.selection.TokenSelection.generateMove(TokenSelection.kt:135)
	at com.r3.corda.sdk.token.workflow.flows.MoveToken$Initiator.call(MoveToken.kt:60)
	at com.r3.corda.sdk.token.workflow.flows.MoveToken$Initiator.call(MoveToken.kt:25)
	at net.corda.node.services.statemachine.FlowStateMachineImpl.run(FlowStateMachineImpl.kt:228)
	at net.corda.node.services.statemachine.FlowStateMachineImpl.run(FlowStateMachineImpl.kt:45)
	at co.paralleluniverse.fibers.Fiber.run1(Fiber.java:1092)
	at co.paralleluniverse.fibers.Fiber.exec(Fiber.java:788)
	at co.paralleluniverse.fibers.RunnableFiberTask.doExec(RunnableFiberTask.java:100)
	at co.paralleluniverse.fibers.RunnableFiberTask.run(RunnableFiberTask.java:91)
	at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511)
	at java.util.concurrent.FutureTask.run(FutureTask.java:266)
	at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.access$201(ScheduledThreadPoolExecutor.java:180)
	at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:293)
	at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
	at net.corda.node.utilities.AffinityExecutor$ServiceAffinityExecutor$1$thread$1.run(AffinityExecutor.kt:63)

Gap in EvolvableTokenType Distribution List Logic

Corda 4.3
Tokens SDK 1.2-SNAPSHOT

Hi,

I would like to know the reasoning behind the gap that I found in the EvolvableTokenType distribution list design.
Here's my example (let's follow in this example the distribution list that is stored in our maintainer: the DMV):

  1. 5 nodes:
    • DMV: Department of Motor Vehicles; issues CarTokenType
    • BMW Dealership: Issues NonFungibleToken of CarTokenType
    • Alice, Bob, and Carol: Holders of the NonFungibleToken
  2. CarTokenType has 2 modifiable attributes:
    • mileage
    • car price (used to pay tax when car is bought)
  3. DMV creates a new CarTokenType: DMV dist list is empty
  4. Alice buys the car from BMW Dealership (i.e. BMW issues the token to Alice): IssueTokensFlow calls UpdateDistributionListFlow, since it's an issue command; only the issuer's distribution list is updated (see here), meaning DMV dist list is still empty
  5. Alice's car goes through yearly inspection, repair shop calls some API to inform DMV, the DMV updates the mileage and estimated price on the CarTokenType; since DMV dist list is empty; only DMV is aware of the update.
  6. Alice wants to sell car to Bob; Alice's node doesn't have the latest version of her CarTokenType.

That's the gap that I'm talking about. Now, let's assume that the DMV added Alice as an observer when they updated CarTokenType. So DMV dist list is still empty but Alice now has the latest version of CarTokenType.

  1. Alice sells the car to Bob; since it's a move; then AbstractMoveTokensFlow will call UpdateDistributionListFlow which in turn will call updateDistributionList here; unlike issue commands which updates only the issuer's distribution list, a move command updates the maintainer (see here), so now DMV dist list has Bob
  2. Car goes through yearly inspection; shop calls API to update DMV, DMV updates CarTokenType, since DMV has Bob in its distribution list; then Bob gets the update (thanx to this line)
  3. Let's say Bob sells the car to Carol; then it's a move command and again the move command updates the DMV (now DMV dist list has Bob and Carol).

So my question is, why this gap on issue? Why only on move commands do holders get added to the maintainer's distribution list, allowing them to get the updates when the maintainer does one?
On issue, to keep data in sync between the holder and the maintainer, I have to add the holder explicitly as an observer in the UpdateEvolvablteToken flow.

FiatCurrency claims to be temporary and doesn't have the claimed properties

 * This is a temporary class while we find a better implementation. It's a wrapper for the Java Currency which doesn't
 * implement the Token SDK interfaces. It also adds specificity around the money, in question, being fiat. Note that
 * fiat money backed stable coins such as Tether would be classed as a [FiatCurrency].
 *
 * @property currency the java.util.Currency which this token type should wrap.

That doesn't look right.

Allow the Issuer to Record Token States

It appears to be impossible to record a FungibleToken inside the issuers vault during issuance or redemption.
This appears to be due to the role selection mechanism in ObserverAwareFinalityFlow.

That means that, even if I pass the issuer as observer on issuance, no state will be recorded in their vault:

@Test
fun `issuer can observe issuance`() {
	val token = 7.GBP issuedBy nodeA.legalIdentity() heldBy nodeB.legalIdentity()
	nodeA.startFlow(IssueTokens(listOf(token), listOf(nodeA.legalIdentity())))
	network.runNetwork()
	val criteria = QueryCriteria.VaultQueryCriteria(
		status = Vault.StateStatus.ALL,
		relevancyStatus = Vault.RelevancyStatus.ALL
	)
	assertThat(nodeB.services.vaultService.queryBy<FungibleToken>(criteria).states, hasSize(equalTo(1)))
	assertThat(nodeA.services.vaultService.queryBy<FungibleToken>(criteria).states, hasSize(equalTo(1))) // FAILS
}

Similarly, on redemption:

@Test
fun `issuer can observe redemption`() {
	val token = 7.GBP issuedBy nodeA.legalIdentity() heldBy nodeB.legalIdentity()
	nodeA.startFlow(IssueTokens(listOf(token), listOf(nodeA.legalIdentity())))
	network.runNetwork()
	nodeB.startFlow(RedeemFungibleTokens(1.GBP, nodeA.legalIdentity(), listOf(nodeA.legalIdentity())))
	network.runNetwork()
	val criteria = QueryCriteria.VaultQueryCriteria(
		status = Vault.StateStatus.ALL,
		relevancyStatus = Vault.RelevancyStatus.ALL
	)
	assertThat(nodeB.services.vaultService.queryBy<FungibleToken>(criteria).states, hasSize(equalTo(2)))
	assertThat(nodeA.services.vaultService.queryBy<FungibleToken>(criteria).states, hasSize(equalTo(2))) // FAILS
}

Warning message in VaultWatcherService

During instantiation of the VaultWatcherService, the following message appears in the log:

[WARN ] 2019-11-26T16:23:44,706Z [main] vault.NodeVaultService._trackBy - trackBy is called with an already existing, open DB transaction. As a result, there might be states missing from both the snapshot and observable, included in the returned data feed, because of race conditions. {}

Is this something to be concerned about?

Hibernate infers incorrect column type for token_class on Azure SQL

Hibernate infers the type varchar(255) for the fields PersistentFungibleToken.tokenClass and PersistentNonFungibleToken.tokenClass. The Liquibase migration script creates both columns as NVARCHAR(255). This leads to the following exception when starting Corda with Token SDK 1.0 deployed after executing the migration.
This has been observed when connecting to an Azure SQL database using the mssql-jdbc-6.2.2.jre8.jar driver.

[ERROR] 17:52:52+0000 [main] internal.NodeStartupLogging.invoke - Exception during node startup: Incompatible schema change detected. Please run the node with database.initialiseSchema=true. Reason: Schema-validation: wrong column type encountered in column [token_class] in table [schem.fungible_token]; found [nvarchar (Types#NVARCHAR)], but expecting [varchar(255) (Types#VARCHAR)] [errorCode=bdopq4, moreInformationAt=https://errors.corda.net/ENT/4.1/bdopq4]

Potential Fixes

  1. Provide a type hint to Hibernate by annotating PersistentFungibleToken.tokenClass and PersistentNonFungibleToken.tokenClass with @Type(type = "org.hibernate.type.StringNVarcharType").
  2. Provide database migrations (fungible-token-schema-v2.changelog-master.xml, non-fungible-token-schema-v2.changelog-master.xml) that change the type of token_class to varchar.

Caveats

Approach 1 does not work inside the contracts sub project when built in deterministic mode as org.hibernate is not available in a dJVM context.
NonFungibleTokenSchema and FungibleTokenSchema cannot easily be moved to the workflows sub project (where org.hibernate is available).

Approach 2 requires a migration of a column to a different data type.

Unable to exit Token Type atomically when all tokens are redeemed

Both Fungible Tokens and their corresponding Token Type cannot be redeemed in the same Corda transaction. Trying to do so results in an error where a state cannot be both a references and an input: https://github.com/corda/corda/blob/release/os/4.4/core/src/main/kotlin/net/corda/core/transactions/TransactionBuilder.kt#L644

However this seems like a valid use case when a non-fungible token (eg. a house) is redeemed and the token type has no remaining functional value because there are no tokens remaining. The token type should be closed because the asset would have to be re-issued onto ledger to gain functional value again.

Preferably the token type and the underlying tokens are exited simultaneously but currently the token type has to be done in a second transaction in a non-atomic fashion. The same problem occurs for redeeming fungible tokens which represent fractional ownership of a non-fungible asset.

What is the intent for redeeming token types when all underlying tokens have been redeemed?

Is it safe to "evenutally" exit all token types once their tokens have been redeemed?

The tokens-money module MUST NOT be fat-jarred into tokens-workflows!

Contract verification in Corda works as follows:

  • The CorDapps involved in a particular transaction are all loaded into AttachmentStorage and assigned an AttachmentId.
  • A signed transaction contains a list of all of the AttachmentIds used to build it.
  • Corda assembles all of the AttachmentIds inside an instance of AttachmentsClassLoader, which is a special "in memory" Java classloader. Corda then recreates the original LedgerTransaction object using classes from AttachmentsClassLoader, along with all of the Contract objects etc, and then invokes LedgerTransaction.verify().

Any CorDapp not included in the signed transaction's list of attachments will therefore not exist in AttachmentsClassLoader. This may result in ClassNotFoundException or NoClassDefFoundError if one of its classes is subsequently referenced when Corda tries to execute LedgerTransaction.verify().

For deterministic contract verifiaction, the attachments are assembled inside the DJVM instead of AttachmentsClassLoader, but otherwise the principle is exactly the same.

The tokens-money CorDapp can be used by tokens-contracts and must therefore be loadable into AttachmentsClassLoader. It is also expected to be loadable into the DJVM because its project applies the deterministic.gradle script plugin. But now that it has been fat-jarred into tokens-workflows, the entire tokens-workflows CorDapp would need to be loaded into AttachmentStorage, along with all of its FlowLogic<?> classes which can never be instantiated inside the DJVM.

Fat-jar tokens-selection if you must, but doing the same with tokens-money files against the architecture of contract verification in Corda 4.x.

“Sender Reference” capability

It is common practice that an operation initiator should be able to assign a reference to the transaction originated by his instruction.(see “Sender Reference”, “Originator Reference” in SWIFT messages standard)
For instance, to accommodate this requirement, the RedeemToken.InitiateRedeem flow could instantiate the TransactionBuilder object, and possibly add to it the reference states considered relevant before sending it to the RedeemToken.IssuerResponder counterparty flow which manages the Token States exit process. The reference states could be provisioned through an extra RedeemToken.InitiateRedeem constructor argument.

Document versoning

Apologies for being lazy, please correct me if i'm wrong bellow:

  • SNAPSHOT versions are not updated at this time
  • RC versions are in their place, i.e. new artifacts overwrite the version

If i'm wrong please point the way. and close.

If not, is there a reason for not rolling out SNAPSHOTS between RCs? Mavens might be an expensive conversion to break if only to reuse the release pipeline; There's lots of infrastructure and humans out there to miss RC is a SNAPSHOT, with reproducible builds pulled under them. Even after figuring out, would one i be able to retrieve the right version? Repo plumbing out there might fail to maintain past revisions for a seemingly non-snapshot without complaints.

Hi, I have this problem when I try to move tokens through partys, net.corda.core.flows.UnexpectedFlowEndException: O=PartyB, L=New York, C=US has finished prematurely and we're trying to send them the finalised transaction. Did they forget to call ReceiveFinalityFlow?

Hi, I have this problem when I try to move tokens from PartyA to Party B, this is the complete exception
[INFO ] 2019-12-11T00:55:12,869Z [Node thread-1] statemachine.StaffedFlowHospital. - Flow [7cbcd75e-cf2a-4ec7-af07-17d042c31eb6] admitted to hospital in state StateMachineState(checkpoint=Checkpoint(invocationContext=InvocationContext(origin=RPC(actor=Actor(id=Id(value=user1), serviceId=AuthServiceId(value=NODE_CONFIG), owningLegalIdentity=O=PartyA, L=London, C=GB)), trace=Trace(invocationId=f562f3be-2754-4305-88ce-44641180b4d9, timestamp: 2019-12-11T00:55:12.454Z, entityType: Invocation, sessionId=8ea73c87-beb7-4a97-9b34-225e44f68c9f, timestamp: 2019-12-11T00:50:13.011Z, entityType: Session), actor=Actor(id=Id(value=user1), serviceId=AuthServiceId(value=NODE_CONFIG), owningLegalIdentity=O=PartyA, L=London, C=GB), externalTrace=null, impersonatedActor=null), ourIdentity=O=PartyA, L=London, C=GB, sessions={SessionId(toLong=-8865563624912587074)=Uninitiated(destination=O=PartyB, L=New York, C=US, initiatingSubFlow=Initiating(flowClass=class com.template.flows.MoveFungibleTokenFlow, classToInitiateWith=class com.template.flows.MoveFungibleTokenFlow, flowInfo=FlowInfo(flowVersion=1, appName=workflows-0.1), subFlowVersion=CorDappFlow(platformVersion=5, corDappName=workflows-0.1, corDappHash=313CBD335D3B29B3146FC37ACF5EB638F6C956DBE36EF9174C7A42E2065FB767), isEnabledTimedFlow=false), sourceSessionId=SessionId(toLong=-8865563624912587074), additionalEntropy=-7645822736075215682), SessionId(toLong=-5309249725331446777)=Initiated(peerParty=O=PartyB, L=New York, C=US, peerFlowInfo=FlowInfo(flowVersion=1, appName=workflows-0.1), receivedMessages=[], initiatedState=Live(peerSinkSessionId=SessionId(toLong=6391133800057730846)), errors=[FlowError(errorId=3432256339453046668, exception=net.corda.core.flows.UnexpectedFlowEndException: Counter-flow errored)], deduplicationSeed=R--5309249725331446777-5204484759134166421), SessionId(toLong=1345013703188110755)=Initiated(peerParty=O=Notary, L=London, C=GB, peerFlowInfo=FlowInfo(flowVersion=5, appName=corda), receivedMessages=[], initiatedState=Live(peerSinkSessionId=SessionId(toLong=8945669728544964326)), errors=[], deduplicationSeed=R-1345013703188110755-8480087332619836515)}, subFlowStack=[Initiating(flowClass=class com.template.flows.MoveFungibleTokenFlow, classToInitiateWith=class com.template.flows.MoveFungibleTokenFlow, flowInfo=FlowInfo(flowVersion=1, appName=workflows-0.1), subFlowVersion=CorDappFlow(platformVersion=5, corDappName=workflows-0.1, corDappHash=313CBD335D3B29B3146FC37ACF5EB638F6C956DBE36EF9174C7A42E2065FB767), isEnabledTimedFlow=false)], flowState=Started(flowIORequest=SendAndReceive({FlowSessionImpl(destination=O=PartyB, L=New York, C=US, sourceSessionId=SessionId(toLong=-5309249725331446777))=FlowSessionImpl(destination=O=PartyB, L=New York, C=US, sourceSessionId=SessionId(toLong=-5309249725331446777))=DD4D28A3E074C470AC7C0A43A36257251F767EDC0FE812601D24E1B6C40B2387}, shouldRetrySend=false), frozenFiber=3EDDE877003693046816913884F70881F306F541E2607314035C9F76793DEB15), errorState=Clean, numberOfSuspends=5), flowLogic=com.template.flows.MoveFungibleTokenFlow@6452e7a5, pendingDeduplicationHandlers=[], isFlowResumed=true, isTransactionTracked=false, isAnyCheckpointPersisted=true, isStartIdempotent=false, isRemoved=false, senderUUID=8c8690e5-68fb-4d9f-98b0-66192a59b429) {actor_id=user1, actor_owning_identity=O=PartyA, L=London, C=GB, actor_store_id=NODE_CONFIG, fiber-id=10000003, flow-id=7cbcd75e-cf2a-4ec7-af07-17d042c31eb6, invocation_id=f562f3be-2754-4305-88ce-44641180b4d9, invocation_timestamp=2019-12-11T00:55:12.454Z, origin=user1, session_id=8ea73c87-beb7-4a97-9b34-225e44f68c9f, session_timestamp=2019-12-11T00:50:13.011Z, thread-id=307, tx_id=BF8511894FDFAAAEA6AB60DD845A78A724D3E9BEBC054D2D9BCC43C70BEE7A8E}
[INFO ] 2019-12-11T00:55:12,869Z [Node thread-1] statemachine.StaffedFlowHospital. - Error 1 of 1: {actor_id=user1, actor_owning_identity=O=PartyA, L=London, C=GB, actor_store_id=NODE_CONFIG, fiber-id=10000003, flow-id=7cbcd75e-cf2a-4ec7-af07-17d042c31eb6, invocation_id=f562f3be-2754-4305-88ce-44641180b4d9, invocation_timestamp=2019-12-11T00:55:12.454Z, origin=user1, session_id=8ea73c87-beb7-4a97-9b34-225e44f68c9f, session_timestamp=2019-12-11T00:50:13.011Z, thread-id=307, tx_id=BF8511894FDFAAAEA6AB60DD845A78A724D3E9BEBC054D2D9BCC43C70BEE7A8E}
net.corda.core.flows.UnexpectedFlowEndException: O=PartyB, L=New York, C=US has finished prematurely and we're trying to send them the finalised transaction. Did they forget to call ReceiveFinalityFlow? (Counter-flow errored)
at net.corda.core.flows.FinalityFlow.call(FinalityFlow.kt:158) ~[corda-core-4.3-RC02.jar:?]
at net.corda.core.flows.FinalityFlow.call(FinalityFlow.kt:39) ~[corda-core-4.3-RC02.jar:?]
at net.corda.node.services.statemachine.FlowStateMachineImpl.subFlow(FlowStateMachineImpl.kt:330) ~[corda-node-4.3-RC02.jar:?]
at net.corda.core.flows.FlowLogic.subFlow(FlowLogic.kt:320) ~[corda-core-4.3-RC02.jar:?]
at com.r3.corda.lib.tokens.workflows.internal.flows.finality.ObserverAwareFinalityFlow.call(ObserverAwareFinalityFlow.kt:75) ~[?:?]
at com.r3.corda.lib.tokens.workflows.internal.flows.finality.ObserverAwareFinalityFlow.call(ObserverAwareFinalityFlow.kt:35) ~[?:?]
at net.corda.node.services.statemachine.FlowStateMachineImpl.subFlow(FlowStateMachineImpl.kt:330) ~[corda-node-4.3-RC02.jar:?]
at net.corda.core.flows.FlowLogic.subFlow(FlowLogic.kt:320) ~[corda-core-4.3-RC02.jar:?]
at com.template.flows.MoveFungibleTokenFlow.call(RealEstateEvolvableFungibleTokenFlow.kt:96) ~[?:?]
at com.template.flows.MoveFungibleTokenFlow.call(RealEstateEvolvableFungibleTokenFlow.kt:66) ~[?:?]
at net.corda.node.services.statemachine.FlowStateMachineImpl.run(FlowStateMachineImpl.kt:270) ~[corda-node-4.3-RC02.jar:?]
at net.corda.node.services.statemachine.FlowStateMachineImpl.run(FlowStateMachineImpl.kt:46) ~[corda-node-4.3-RC02.jar:?]
at co.paralleluniverse.fibers.Fiber.run1(Fiber.java:1092) ~[quasar-core-0.7.10-jdk8.jar:0.7.10]
at co.paralleluniverse.fibers.Fiber.exec(Fiber.java:788) ~[quasar-core-0.7.10-jdk8.jar:0.7.10]
at co.paralleluniverse.fibers.RunnableFiberTask.doExec(RunnableFiberTask.java:100) ~[quasar-core-0.7.10-jdk8.jar:0.7.10]
at co.paralleluniverse.fibers.RunnableFiberTask.run(RunnableFiberTask.java:91) ~[quasar-core-0.7.10-jdk8.jar:0.7.10]
at java.util.concurrent.Executors$RunnableAdapter.call(Unknown Source) ~[?:1.8.0_221]
at java.util.concurrent.FutureTask.run(Unknown Source) ~[?:1.8.0_221]
at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.access$201(Unknown Source) ~[?:1.8.0_221]
at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(Unknown Source) ~[?:1.8.0_221]
at java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source) ~[?:1.8.0_221]
at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source) ~[?:1.8.0_221]
at net.corda.node.utilities.AffinityExecutor$ServiceAffinityExecutor$1$thread$1.run(AffinityExecutor.kt:63) ~[corda-node-4.3-RC02.jar:?]

And this is the code of my flow

class MoveFungibleTokenFlow(
private val me: Party,
private val holder: Party,
private val quantity: Long,
val auditor : Party) : FlowLogic() {

    override val progressTracker = ProgressTracker()

    @Suspendable
    @Throws(FlowException::class)
    override fun call(): SignedTransaction {
        val notary =  serviceHub.networkMapCache.notaryIdentities.first()
        val transactionBuilder = TransactionBuilder( notary = notary)
        val localTokenSelector = LocalTokenSelector(serviceHub)
        val tokenMXN : TokenType  = FiatCurrency.getInstance("MXN");
        val amount = Amount(quantity,tokenMXN);
        val partiesAndAmounts : List<Pair<AbstractParty, Amount<TokenType>>> = listOf(Pair(holder,amount))
        val session = initiateFlow(holder)
        val (inputs, outputs) = localTokenSelector.generateMove(
                lockId = transactionBuilder.lockId, // Defaults to FlowLogic.currentTopLevel?.runId?.uuid ?: UUID.randomUUID()
                partiesAndAmounts  =  partiesAndAmounts,
                changeHolder = me,
                queryBy = TokenQueryBy(issuer = ourIdentity, predicate = { it.state.notary == notary })
        )

       addMoveTokens(transactionBuilder, inputs, outputs)
       // subFlow(IdentitySyncFlow.Send(session, transactionBuilder.toWireTransaction(serviceHub)))
        val ourSigningKeys = transactionBuilder.toLedgerTransaction(serviceHub).ourSigningKeys(serviceHub)
        val initialStx = serviceHub.signInitialTransaction(transactionBuilder, signingPubKeys = ourSigningKeys)
        val stx = subFlow(CollectSignaturesFlow(initialStx, listOf(session), ourSigningKeys))
        return subFlow(ObserverAwareFinalityFlow(stx, listOf(session)))
    }
}


    @InitiatedBy(MoveFungibleTokenFlow::class)
    class MoveFungibleTokenFlowHandler(val otherSession: FlowSession) : FlowLogic<Unit>() {
        @Suspendable
        override fun call() {
            val priceNotification = otherSession.receive<PriceNotification>().unwrap { it }
            val changeHolder = serviceHub.keyManagementService.freshKeyAndCert(ourIdentityAndCert, false).party.anonymise()
            val (inputs, outputs) = LocalTokenSelector(serviceHub).generateMove(
                    lockId = runId.uuid,
                    partiesAndAmounts = listOf(Pair(otherSession.counterparty, priceNotification.amount)),
                    changeHolder = changeHolder
            )
            subFlow(SendStateAndRefFlow(otherSession, inputs))
            otherSession.send(outputs)
           // subFlow(IdentitySyncFlow.Receive(otherSession))
            subFlow(object : SignTransactionFlow(otherSession) {
                override fun checkTransaction(stx: SignedTransaction) {
                    // We should perform some basic sanity checks before signing the transaction. This step was omitted for simplicity.
                }
            })
            subFlow(ObserverAwareFinalityFlowHandler(otherSession))
        }
    }

}

java.lang.SecurityException at FlowTests.kt in corda-template-kotlin

I am following the documentation in https://github.com/corda/token-sdk to get the build and test the corda template. The ./gradlew test results in an error as this :
`> Task :workflows:test

com.template.ContractTests > dummy test FAILED
java.lang.SecurityException at ContractTests.kt:7

com.template.FlowTests > dummy test FAILED
java.lang.SecurityException at FlowTests.kt:9`

I want to jumpstart on using the token-sdk but could not progress further

Multiple issuance calls will cause multiple distribution list entries

In the case when an Issuer issues 10 ACME tokens to Receiver multiple times, this will result in the Receiver with a LinearId for ACME being included in the DistributionList multiple times. I'd say that's a bug and would expect the DistributionList to only contain a single entry for a Token(LinearId) and Party combination.

If you agree with me, please give me some guidance if you'd prefer the addPartyToDistributionList or any DistributionList helper function to be upsert-like to if you'd like to do a check as part of the flow.

java.lang.IllegalStateException: Insufficient spendable states identified for 0.01 TokenType(tokenIdentifier='MXN', fractionDigits=2)

Hi,when trying to use open source 4,1, and 4.3 version, using both token-sdk-1.0 and the latest token-sdk-1.1. we would get very, very slow at best 2 tx/s per node. We suspect the token-sdk is also giving us problems. Functionally it works fine, but when trying to stress it out, we noticed that it was very slow with logs showing this:

[WARN ] 2019-12-09T02:00:20,888Z [Node thread-1] selection.TokenSelection. - TokenType selection failed on attempt 7. {actor_id=user1, actor_owning_identity=O=Banxico, L=London, C=GB, actor_store_id=NODE_CONFIG, fiber-id=10000008, flow-id=0c4f209b-84cc-47a6-9371-00b2e65dbf9c, invocation_id=f56a6cc9-580c-
4076-bb14-b5b3942d102b, invocation_timestamp=2019-12-09T02:00:13.770Z, origin=user1, session_id=e9b0bd3d-599a-474c-abf0-a2d557671d09, session_timestamp=2019-12-09T01:54:07.346Z, thread-id=145}

[WARN ] 2019-12-09T02:00:32,480Z [Node thread-1] selection.TokenSelection. - TokenType selection failed on attempt 8. {actor_id=user1, actor_owning_identity=O=Banxico, L=London, C=GB, actor_store_id=NODE_CONFIG, fiber-id=10000017, flow-id=10bb4d7a-079f-44ba-b22b-df826fc7623f, invocation_id=398ae9f8-598e-45a0-b1b0-29e48f14394d, invocation_timestamp=2019-12-09T02:00:23.645Z, origin=user1, session_id=e9b0bd3d-599a-474c-abf0-a2d557671d09, session_timestamp=2019-12-09T01:54:07.346Z, thread-id=145}

[WARN ] 2019-12-09T03:33:21,400Z [Node thread-1] selection.VaultWatcherService. - Received a consumption event for a token E7499056A875F4C399DD30B4CB8C5D6346FBE8C21A9161449B4A985D0E26254A(0) which was either not present in the token cache, or was not locked {actor_id=user1, actor_owning_identity=O=Banorte, L=New York, C=US, actor_store_id=NODE_CONFIG, fiber-id=10000677, flow-id=367cc7c6-6a8c-4bf6-a56e-e2b02392c1ea, invocation_id=8fcf9e1e-8727-46a2-904b-7270eb10b3bd, invocation_timestamp=2019-12-09T03:33:16.504Z, origin=user1, session_id=271a869f-31f6-45c4-8610-42b1120753de, session_timestamp=2019-12-09T02:50:23.314Z, thread-id=144}

Which eventually would lead to a

INFO ] 2019-12-09T02:00:22,092Z [Node thread-1] statemachine.StaffedFlowHospital. - Flow error allowed to propagate {actor_id=user1, actor_owning_identity=O=Banxico, L=London, C=GB, actor_store_id=NODE_CONFIG, fiber-id=10000008, flow-id=0c4f209b-84cc-47a6-9371-00b2e65dbf9c, invocation_id=f56a6cc9-580c-4 076-bb14-b5b3942d102b, invocation_timestamp=2019-12-09T02:00:13.770Z, origin=user1, session_id=e9b0bd3d-599a-474c-abf0-a2d557671d09, session_timestamp=2019-12-09T01:54:07.346Z, thread-id=145} java.lang.IllegalStateException: Insufficient spendable states identified for 0.01 TokenType(tokenIdentifier='MXN', fractionDigits=2)

Issues with import statements using latest token-template

If I follow the instructions in the documentation for the Corda Token SDK Setup (but switched to Java):

git clone http://github.com/corda/cordapp-template-java
cd cordapp-template-java
git checkout token-template

This currently produces (from build.gradle file):

corda_release_group = 'net.corda'
corda_release_version = '4.1'
tokens_release_group = 'com.r3.corda.lib.tokens'
tokens_release_version = '1.1-SNAPSHOT'

If you open class ExampleFlowWithEvolvableToken in IntelliJ you will see it is having trouble with the import statements:

import com.r3.corda.lib.tokens.contracts.states.NonFungibleToken;
import com.r3.corda.lib.tokens.contracts.types.IssuedTokenType;
import com.r3.corda.lib.tokens.contracts.types.TokenPointer;
import com.r3.corda.lib.tokens.contracts.utilities.TransactionUtilitiesKt;
import com.r3.corda.lib.tokens.workflows.flows.rpc.CreateEvolvableTokens;
import com.r3.corda.lib.tokens.workflows.flows.rpc.IssueTokens;

I had been working with:

corda_release_group = 'net.corda'
corda_release_version = '4.1'
tokens_release_group = 'com.r3.corda.lib.tokens'
tokens_release_version = '1.0-RC03'

...and it had no issues. I can change the tokens_release_version but I just wanted to let the team working on the Token SDK know what I am seeing.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.