带有令牌和帐户的 Corda
Corda with token and accounts
我们正在使用 Kotlin 在 Corda 处理代币和账户。我将详细说明这个场景。
我们有一个 node1 和一个 node2。
我们创建了一个扩展自 TokenType 的 "OurTokenType"。
我们在 node1 上创建了两个帐户(卖家和买家),并与 node2 共享。
根据应用程序的业务规则,节点 2 是发行令牌 (FungibleToken) 的人,发行工作正常。最后,节点 1 和节点 2 可以访问发行交易的 FungibleStates。
我们的问题在于这些代币的转移。当我们尝试将代币从账户卖家转移到买家时。
在我们的场景中,令牌的传输可能发生在节点 1 或节点 2 上。
当我们通过作为账户主机的节点 1 进行转账时,我们可以使用有效的 MoveFungibleTokensFlow class 并将节点 1 上的 FungibleStates 更新为正确的值。但是,当我们在 observerSessions 参数中添加 node2 作为观察者时,node2 上的 FungibleStates 没有正确更新。
当我们使用 MoveFungibleTokensFlow class 通过不是账户主机的节点 2 进行转账时,它不起作用,它会生成 com.r3.corda.lib.tokens.selection.InsufficientBalanceException 的异常:已识别的可花费状态不足, 即使余额 .
我的问题是,我可以使用 MoveFungibleTokensFlow class 在帐户之间转移,即使它们在另一台主机上吗?
当我们 运行 在托管帐户的节点上时,使用 observerSessions 更新 FungibleStates 有什么问题?
或者,如果我必须遵循 link https://github.com/corda/samples-kotlin/tree/master/Accounts/worldcupticketbooking?
的示例
让我把你的问题分成两部分:
观察者会话不会自动更新:
这是我们如何触发观察者会话更新的示例:https://github.com/corda/samples-kotlin/blob/master/Tokens/stockpaydividend/workflows/src/main/kotlin/net/corda/samples/stockpaydividend/flows/AnnounceDividend.kt#L37
这将确保只要维护者进行更新,观察者的令牌状态就会更新。 (注意:只有维护者应该进行更新,而不是所有者)
两方之间的可替代代币转移:是的。这是可行的。这行代码是 worldcupticketbooking 示例中 FungibleToken 转移的开始: https://github.com/corda/samples-kotlin/blob/master/Accounts/worldcupticketbooking/workflows/src/main/kotlin/com/t20worldcup/flows/DVPAccountsHostedOnDifferentNodes.kt#L102 它确实有效。
我看到你提到你在 InsufficientBalanceException
上有一条错误消息,如果我是你,我会从那里开始挖掘,看看正在查询的令牌到底是哪个。
MoveFungibleTokensFlow
没有指定谁是移动令牌的来源的输入参数,这是因为它将流的发起者视为令牌的来源。
class MoveFungibleTokensFlow
@JvmOverloads
constructor(
val partiesAndAmounts: List<PartyAndAmount<TokenType>>,
override val participantSessions: List<FlowSession>,
override val observerSessions: List<FlowSession> = emptyList(),
val queryCriteria: QueryCriteria? = null,
val changeHolder: AbstractParty? = null
) : AbstractMoveTokensFlow() {
你说的不对"both node1 and node2 see the issued tokens",在FungibleToken
中唯一的参与者是代币的holder
,所以当代币发给买卖双方时帐户,唯一的参与者是托管这些帐户的节点(即 node1)。
回到我的第一点,因为只有节点 1 有发行的令牌,而你是 运行 节点 2 上的移动流(该流将节点 2 视为令牌的来源,但 node2 没有它们);这就是您收到余额不足错误的原因。
- 即使您在向买卖双方发行代币时添加了节点 2 作为观察者(即节点 1 和节点 2 都有生成的代币);如果你深入研究继承自
AbstractMoveTokensFlow
的 MoveFungibleTokensflow
的代码,它依赖 ObserverAwareFinalityFlow
来签署交易,你会在 ObserverAwareFinalityFlow
内部看到它不会调用CollectSignatures
流,它只在本地签署交易(参见 here);这意味着只有持有账户私钥的节点才能签署移动命令,因为节点 1 是买卖双方的 host
;那么 node1 是 private/public 密钥的所有者,只有 node1 可以代表买卖双方签名。因此,即使您与 node2 共享买家和卖家帐户;只有 node1 可以签名,并且由于您从 node2 调用 MoveFungibleTokensFlow
(您的第二个场景),当它到达需要代表卖家签名的部分(移动其令牌)时它将失败,因为 node2不拥有该帐户的私钥。
- 附带说明一下,当您从节点 1 调用
MoveFungibleTokesnFlow
将卖方的代币转移给买方时;确保您只为属于卖家的代币提供 queryCriteria
到 select 的价值;如果您不提供价值;然后该流程将选择托管在 node1 上的任何令牌,因此您最终可能会移动属于其他帐户的令牌。
- 另外请确保为
changeHolder
提供一个值,以便更改返回给卖家,如果您将其留空;任何由此产生的更改都将分配给发起节点(即 node1)而不是帐户。
- 您可以在 my article on Tokens SDK 中找到很多有用的提示。
- 另外,R3 最近发布了一个免费的 Corda 课程;它在 Tokens SDK 上有一个 great section。
- 为了能够使用节点 1 或节点 2 将代币从卖家转移到买家,您必须依赖效用函数
addMoveTokens()
而不是现成的流程(即 MoveFungibleTokensFlow
)(由于上述原因)。所以你必须自己创建交易,然后使用 addMoveTokens()
添加要移动的代币,然后你必须使用 CollectSignatures
流程收集(卖家的)签名(卖家将在响应者中签名流动);您还必须负责完成交易。
- 为了澄清上面的流程,你的流程应该检查它是否是卖家的主机;然后它可以在本地签名,如果它不是主机;然后你必须用帐户的主机创建一个
FlowSession
,这样你就可以收集它的签名(即它批准移动它持有的令牌)。
- 示例存储库有 some examples 使用
addMoveTokens()
;我建议花一些时间来探索它们。
我们正在使用 Kotlin 在 Corda 处理代币和账户。我将详细说明这个场景。 我们有一个 node1 和一个 node2。 我们创建了一个扩展自 TokenType 的 "OurTokenType"。 我们在 node1 上创建了两个帐户(卖家和买家),并与 node2 共享。 根据应用程序的业务规则,节点 2 是发行令牌 (FungibleToken) 的人,发行工作正常。最后,节点 1 和节点 2 可以访问发行交易的 FungibleStates。 我们的问题在于这些代币的转移。当我们尝试将代币从账户卖家转移到买家时。 在我们的场景中,令牌的传输可能发生在节点 1 或节点 2 上。 当我们通过作为账户主机的节点 1 进行转账时,我们可以使用有效的 MoveFungibleTokensFlow class 并将节点 1 上的 FungibleStates 更新为正确的值。但是,当我们在 observerSessions 参数中添加 node2 作为观察者时,node2 上的 FungibleStates 没有正确更新。 当我们使用 MoveFungibleTokensFlow class 通过不是账户主机的节点 2 进行转账时,它不起作用,它会生成 com.r3.corda.lib.tokens.selection.InsufficientBalanceException 的异常:已识别的可花费状态不足, 即使余额 .
我的问题是,我可以使用 MoveFungibleTokensFlow class 在帐户之间转移,即使它们在另一台主机上吗? 当我们 运行 在托管帐户的节点上时,使用 observerSessions 更新 FungibleStates 有什么问题? 或者,如果我必须遵循 link https://github.com/corda/samples-kotlin/tree/master/Accounts/worldcupticketbooking?
的示例让我把你的问题分成两部分:
观察者会话不会自动更新: 这是我们如何触发观察者会话更新的示例:https://github.com/corda/samples-kotlin/blob/master/Tokens/stockpaydividend/workflows/src/main/kotlin/net/corda/samples/stockpaydividend/flows/AnnounceDividend.kt#L37 这将确保只要维护者进行更新,观察者的令牌状态就会更新。 (注意:只有维护者应该进行更新,而不是所有者)
两方之间的可替代代币转移:是的。这是可行的。这行代码是 worldcupticketbooking 示例中 FungibleToken 转移的开始: https://github.com/corda/samples-kotlin/blob/master/Accounts/worldcupticketbooking/workflows/src/main/kotlin/com/t20worldcup/flows/DVPAccountsHostedOnDifferentNodes.kt#L102 它确实有效。
我看到你提到你在 InsufficientBalanceException
上有一条错误消息,如果我是你,我会从那里开始挖掘,看看正在查询的令牌到底是哪个。
MoveFungibleTokensFlow
没有指定谁是移动令牌的来源的输入参数,这是因为它将流的发起者视为令牌的来源。
class MoveFungibleTokensFlow
@JvmOverloads
constructor(
val partiesAndAmounts: List<PartyAndAmount<TokenType>>,
override val participantSessions: List<FlowSession>,
override val observerSessions: List<FlowSession> = emptyList(),
val queryCriteria: QueryCriteria? = null,
val changeHolder: AbstractParty? = null
) : AbstractMoveTokensFlow() {
你说的不对"both node1 and node2 see the issued tokens",在
FungibleToken
中唯一的参与者是代币的holder
,所以当代币发给买卖双方时帐户,唯一的参与者是托管这些帐户的节点(即 node1)。回到我的第一点,因为只有节点 1 有发行的令牌,而你是 运行 节点 2 上的移动流(该流将节点 2 视为令牌的来源,但 node2 没有它们);这就是您收到余额不足错误的原因。
- 即使您在向买卖双方发行代币时添加了节点 2 作为观察者(即节点 1 和节点 2 都有生成的代币);如果你深入研究继承自
AbstractMoveTokensFlow
的MoveFungibleTokensflow
的代码,它依赖ObserverAwareFinalityFlow
来签署交易,你会在ObserverAwareFinalityFlow
内部看到它不会调用CollectSignatures
流,它只在本地签署交易(参见 here);这意味着只有持有账户私钥的节点才能签署移动命令,因为节点 1 是买卖双方的host
;那么 node1 是 private/public 密钥的所有者,只有 node1 可以代表买卖双方签名。因此,即使您与 node2 共享买家和卖家帐户;只有 node1 可以签名,并且由于您从 node2 调用MoveFungibleTokensFlow
(您的第二个场景),当它到达需要代表卖家签名的部分(移动其令牌)时它将失败,因为 node2不拥有该帐户的私钥。 - 附带说明一下,当您从节点 1 调用
MoveFungibleTokesnFlow
将卖方的代币转移给买方时;确保您只为属于卖家的代币提供queryCriteria
到 select 的价值;如果您不提供价值;然后该流程将选择托管在 node1 上的任何令牌,因此您最终可能会移动属于其他帐户的令牌。 - 另外请确保为
changeHolder
提供一个值,以便更改返回给卖家,如果您将其留空;任何由此产生的更改都将分配给发起节点(即 node1)而不是帐户。 - 您可以在 my article on Tokens SDK 中找到很多有用的提示。
- 另外,R3 最近发布了一个免费的 Corda 课程;它在 Tokens SDK 上有一个 great section。
- 为了能够使用节点 1 或节点 2 将代币从卖家转移到买家,您必须依赖效用函数
addMoveTokens()
而不是现成的流程(即MoveFungibleTokensFlow
)(由于上述原因)。所以你必须自己创建交易,然后使用addMoveTokens()
添加要移动的代币,然后你必须使用CollectSignatures
流程收集(卖家的)签名(卖家将在响应者中签名流动);您还必须负责完成交易。 - 为了澄清上面的流程,你的流程应该检查它是否是卖家的主机;然后它可以在本地签名,如果它不是主机;然后你必须用帐户的主机创建一个
FlowSession
,这样你就可以收集它的签名(即它批准移动它持有的令牌)。 - 示例存储库有 some examples 使用
addMoveTokens()
;我建议花一些时间来探索它们。