Выпуск токена на Corda - PullRequest
       8

Выпуск токена на Corda

0 голосов
/ 22 сентября 2018

Может ли организация, работающая с узлом Corda, проверить выданное количество определенного токена в сети, не зная, кому принадлежит количество этих токенов?

(Например, какая-то сторона выпускает золотые токены, подкрепленные физическими данными.золото. Как инвестор может проверить общую поставку золотых жетонов в сети? В настоящее время вы либо теряете конфиденциальность, либо вынуждены доверять третьей стороне, например узлу регулятора.)

1 Ответ

0 голосов
/ 22 сентября 2018

Вот возможное решение.

В приведенном ниже коде 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()
            }
        }
    }
}
...