corda - Corda 上的代币发行
问题描述
运行 Corda 节点的实体能否在不知道谁拥有这些代币的数量的情况下验证网络中某个代币的发行量?
(例如,某方正在发行由实物黄金支持的黄金代币。投资者如何验证网络中黄金代币的总供应量?目前您要么失去隐私,要么必须信任第三方,如监管节点。)
解决方案
这是一个可能的解决方案。
在下面的代码中,TokenState
定义了一个带有附加issuingHash
字段的标准标记。TokenContract
强制将此字段设置为在令牌已发行但可以传输之前最初发行令牌的交易的哈希值。一旦设置,issuingHash
就永远无法修改。
例如,假设有一些发行交易的哈希值7925679A6414AEBF69ED1A250E3E1E4452A4384529E3B690A4B47DD6A9918B93
生成 1,000,000 个代币。强制在下一个事务中将其TokenContract
设置为令牌。issuingHash
现在,如果原始发行交易被广泛共享,那么每个人都可以确定只有 1,000,000 个代币issuingHash
存在。公证池将拒绝任何未来将issuingHash
发行交易的输出设置为相同哈希的尝试(这将构成双花尝试),并且在设置之前不能转移代币issuingHash
。
然后你可以说你只愿意用 代币支付issuingHash
7925679A6414AEBF69ED1A250E3E1E4452A4384529E3B690A4B47DD6A9918B93
,知道只有 1,000,000 存在。
data class TokenState(val owner: Party, val amount: Int, val issuingHash: SecureHash?) : ContractState {
override val participants: List<AbstractParty> = listOf()
}
interface TokenCommands : CommandData {
class Issue : TokenCommands
class SetIssuingHash : TokenCommands
class Transfer : TokenCommands
}
class TokenContract : Contract {
override fun verify(tx: LedgerTransaction) {
val tokenCommand = tx.commandsOfType<TokenCommands>().singleOrNull() ?: throw IllegalArgumentException()
val tokenInputs = tx.inputsOfType<TokenState>()
val tokenOutputs = tx.outputsOfType<TokenState>()
when (tokenCommand.value) {
is TokenCommands.Issue -> {
if (tokenInputs.isNotEmpty()) throw IllegalArgumentException()
val tokenOutput = tokenOutputs.singleOrNull() ?: throw IllegalArgumentException()
if (tokenOutput.issuingHash != null) throw IllegalArgumentException()
}
is TokenCommands.SetIssuingHash -> {
val tokenInput = tokenInputs.singleOrNull() ?: throw IllegalArgumentException()
val tokenOutput = tokenOutputs.singleOrNull() ?: throw IllegalArgumentException()
if (tokenInput.issuingHash != null) throw IllegalArgumentException()
if (tokenOutput.issuingHash != tx.inputs[0].ref.txhash) throw IllegalArgumentException()
if (tokenOutput.copy(issuingHash = null) != tokenInput) throw IllegalArgumentException()
}
// Extend this logic to allow tokens with different `issuingHash`s to be used in the same transaction.
is TokenCommands.Transfer -> {
if ((tokenInputs + tokenOutputs).any { it.issuingHash == null }) throw IllegalArgumentException()
if ((tokenInputs + tokenOutputs).map { it.issuingHash }.toSet().size != 1) throw IllegalArgumentException()
if (tokenInputs.sumBy { it.amount } != tokenOutputs.sumBy { it.amount }) throw IllegalArgumentException()
}
}
}
}
推荐阅读
- wkhtmltopdf - 为什么 wkhtmltopdf 页眉和页脚仅应用于目录页 (toc)?
- node.js - 如何永远监控服务自动停止和重启
- java - 映射PostgreSQL枚举时如何在Hibernate中复制@Type和@Convert的逻辑?
- python - 将具有多维值的一维数组转换为多维数组
- python - Django MySQL 数据库位置和设置
- python - 提交按钮不起作用并重定向到 Django 中的 404 错误页面
- gemfire - 在 Gemfire 服务器日志中发现“线程已用尽”
- visual-studio - HTK 在 windows10 中安装 / 找不到 VC98
- react-native - 如何使用 join() 在数组中渲染反应原生组件?
- pandas - 熊猫数据框的 yaml 转储