Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Gap in EvolvableTokenType Distribution List Logic #197

Open
adelrustum opened this issue Apr 13, 2020 · 1 comment
Open

Gap in EvolvableTokenType Distribution List Logic #197

adelrustum opened this issue Apr 13, 2020 · 1 comment

Comments

@adelrustum
Copy link

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.

@TywinLannister1313
Copy link

I ran into the same problem. I think the code in UpdateDistributionListFlow has been written to assume an EvolvableTokenType only has a single maintainer during an Issue. Whereas the Move logic properly assumes there may be more than one maintainer. The comments confirm the developer's thinking on this:

class UpdateDistributionListFlow(val signedTransaction: SignedTransaction) : FlowLogic<Unit>() {

...

        if (issueCmds.isNotEmpty()) {
            // If it's an issue transaction then the party calling this flow will be the issuer and they just need to
            // update their local distribution list with the parties that have been just issued tokens.
            val issueTypes: List<TokenPointer<*>> = issueCmds.map { it.token.tokenType }.mapNotNull { it as? TokenPointer<*> }
            progressTracker.currentStep = ADD_DIST_LIST
            val issueStates: List<AbstractToken> = tokensWithTokenPointers.filter {
                it.tokenType in issueTypes
            }
            addToDistributionList(issueStates)    // <- !!! incorrectly assumes only a single maintainer
        }
        if (moveCmds.isNotEmpty()) {
            // If it's a move then we need to call back to the issuer to update the distribution lists with the new
            // token holders.
            val moveTypes = moveCmds.map { it.token.tokenType }
            progressTracker.currentStep = UPDATE_DIST_LIST
            val moveStates = tokensWithTokenPointers.filter { it.tokenType in moveTypes }
            updateDistributionList(moveStates)    // <- !!! properly assumes there is multiple maintainers
        }

I have been getting around this by always self-issuing tokens and then performing a move. This works as long as your Maintainers are also Participants.

After the issue the Distribution List will be missing on the other maintainer's nodes. But since they are Participants they will have the proper state in their vault.

When the tokens are moved then the Distribution Lists are properly built on the other maintainers.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants