Corda 如何正确制作不可隐藏的文档';独一无二的

Corda 如何正确制作不可隐藏的文档';独一无二的,corda,Corda,问题: 用于构建不可隐藏的令牌的令牌类型的令牌标识符必须是唯一的字符串吗 冗长的背景: 该文件清楚地概述了“事实上,开发人员有责任确保非隐藏对象的两个实例都不引用同一个链外或链上对象…” 我的印象是,UniqueIdentifier是我确保唯一性的方式: TokenType tokenType = new TokenType("Toyota Corolla", 0); IssuedTokenType issuedTokenType = new IssuedTokenType(

问题:

用于构建
不可隐藏的令牌
令牌类型的
令牌标识符
必须是唯一的字符串吗

冗长的背景:

该文件清楚地概述了“事实上,开发人员有责任确保
非隐藏对象的两个实例都不引用同一个链外或链上对象…”

我的印象是,
UniqueIdentifier
是我确保唯一性的方式:

TokenType tokenType = new TokenType("Toyota Corolla", 0);
IssuedTokenType issuedTokenType = new IssuedTokenType(partyA, tokenType);

String VIN = "1G2JB12F047226515";
UUID uuid = UUID.randomUUID();
UniqueIdentifier uniqueIdentifier = new UniqueIdentifier(VIN, uuid);

NonFungibleToken nonFungibleToken = new NonFungibleToken(issuedTokenType, partyA, uniqueIdentifier);
这使我能够定义无限的丰田花冠,每个都有自己独特的
UUID
和车辆识别号(VIN)

moveNofGibleTokens()
流允许我指定一个
QueryCriteria
来隔离我想要移动的特定
NofGibleToken
(我使用
LinearStateQueryCriteria
指定
UUID
):

但是,当我想兑换
非永久性令牌时,
兑换非永久性令牌()
流只允许我指定
令牌类型

subFlow(new RedeemNonFungibleTokens(tokenType, issuer, observers));
这意味着我无法通过它的
UUID
来识别
非隐藏项。如果您执行我在上面所做的操作,当我尝试赎回时,您将收到以下错误:

Exactly one held token of a particular type TokenType(tokenIdentifier=' Toyota Corolla ', fractionDigits=0) should be in the vault at any one time.
如果是这种情况,则
TokenType
tokenindicator
(“丰田花冠”)必须是唯一性的来源。我必须这样做:

TokenType tokenType = new TokenType("Toyota Corolla-" + UUID.randomUUID(), 0);
这是正确的还是我遗漏了什么

当我开始编写令牌测试的赎回部分时,我真的很惊讶,我想“那么在
不可隐藏的令牌中
唯一标识符
的目的是什么呢?”

  • 在不可替代代币的情况下,代币类型和代币之间的关系为一对一;这就是为什么兑换流只接受
    TokenType
    参数的原因
  • 查看
    movenongibletokens
    flow输入参数,它们与第一个语句有点矛盾;因为即使是流上的注释也表明它应该一次用于一个
    TokenType
    ,这意味着不需要
    queryCriteria
    参数,因为您已经指定了要在
    PartyAndToken
    参数中移动的令牌(TokenType)。我会将此讨论转发给R3工程师以获得澄清
  • 至于您的问题,您在不可替换令牌中需要唯一标识符的原因是它扩展了
    LinearState
    (由该
    UUID
    标识)
  • 记住,状态在Corda中是不可变的,那么如何模拟更新呢?您可以使用
    LinearState
    进行购买,例如,如果您的不可替换代币是一辆汽车,并且您希望更换汽车的车主(即更新代币的
    持有人
    );然后创建一个事务,其中输入为当前令牌,输出为更新的令牌,该令牌应具有与输入相同的
    linearId
    ;通过这种方式,输出和输入被绑定在一起,现在您可以通过查询共享的
    linearId
    来跟踪特定状态的更新历史
  • 旁注:您的
    LinearState
    应该有2个构造函数;一个是分配一个随机的
    linearId
    ,您应该在创建新状态时使用它,另一个是将
    linearId
    作为输入参数的构造函数;当您创建更新事务的输出时,应该使用此构造函数(这样您就可以使用输入的
    linearId
    创建输出),并且您必须使用
    @CordaSerializable
    注释标记该构造函数,以便Corda在检查某个流时使用它(即序列化然后反序列化您的状态)否则Corda将使用另一个构造函数,并在反序列化您的状态(当流恢复时)时为您的
    linearId
    分配一个新的随机值,而您基本上以不同的状态结束
  • 我建议您在汽车示例中使用
    EvolvableTokenType
    ,而不是
    TokenType
    ;这将允许您添加自定义属性(VIN、价格、里程等),您可以控制哪些属性可以更新(价格、里程),哪些属性不能更新(VIN);请在R3的官方免费Corda课程中了解更多信息

没错!–这是MoveNofGibleTokens()中的QueryCriteria。我认为这是理解NofGibleToken的关键,也就是说,这就是如何从具有相同标记标识符的标记类型构建NofGibleToken,同时仍然能够使用LinearState属性区分它们(UUID等)。如果每个TokenType都必须有一个唯一的TokenIdentifier,那么很难搜索“所有丰田花冠”,这是一个关于NoFungibleToken的设计理念的问题。感谢您花了这么多时间来写一个完整的答案。
TokenType tokenType = new TokenType("Toyota Corolla-" + UUID.randomUUID(), 0);