首页 > 解决方案 > Corda - 设计安全合约

问题描述

最近我一直在研究 Corda 中合约命令的安全性和漏洞方面。关于某些合约命令约束是否应该严格或是否应该放宽以允许不同输入、输出和命令的交易组合出现了争论。

问题是,虽然我可以看到允许交易组合的好处,但我觉得放松的合约命令约束实际上会带来安全漏洞,而且在我看来,最好在合约级别保护这些漏洞,这样签署命令的参与者通过整体合同验证达成共识,而不是依赖于流级别检查,这可能被开发人员忽略或被恶意节点规避。

示例 - 破产声明

这个例子允许网络上的节点宣布破产。假设在这种情况下,宣布破产状态只是宣布​​破产的节点的身份和原因。

@BelongsToContract(BankruptcyDeclarationContract::class)
data class BankruptcyDeclarationState(
    override val owner: AbstractParty,
    val reason: String    
) : OwnableState { ... }

严格验证

严格的验证要求,在签发...

fun verifyIssue(tx: LedgerTransaction, signers: Set<PublicKey>) = requireThat {
    "Zero input states must be consumed." using (tx.inputs.isEmpty())
    "One output state must be created." using (tx.outputs.size == 1)

    val state = tx.outputsOfType<BankruptcyDeclarationState>().single()
    "Only the owner must sign." using (state.owner.owningKey == signers.single())
}

宽松的验证

宽松的验证要求,在发行时...

fun verifyIssue(tx: LedgerTransaction, signers: Set<PublicKey>) = requireThat {
    val inputs = tx.inputsOfType<BankruptcyDeclarationState>()
    val outputs = tx.outputsOfType<BankruptcyDeclarationState>()

    "Zero input states of type BankruptcyDeclarationState must be consumed." using 
        (inputs.isEmpty())
    "One output state of type BankruptcyDeclarationState must be created." using 
        (outputs.size == 1)
    "Only the owner must sign." using (outputs.single().owner.owningKey == signers.single())
}

观察

识别漏洞

假设我们选择将合约命令约束建模为放松,以便我们可以组合交易。另外,假设我们有一个合约命令ObligationState,在发布时需要:

现在我们有两种状态类型和两个合约命令,我们可以组成一个使用两者的交易,并识别漏洞。在这里假设bob正在发起这个事务。

val transaction = with(TransactionBuilder(notary)) {

    addOutputState(ObligationState(alice, bob), ObligationContract.ID)
    addCommand(ObligationContract.Issue(), aliceKey, bobKey)

    addOutputState(BankruptcyDeclarationState(alice, "..."), BankruptcyDeclarationContract.ID)
    addCommand(BankruptcyDeclarationContract.Issue(), aliceKey)
}

请记住,只有必须签名的所有者,以及BankruptcyDeclarationState必须签名的义务人和债权人ObligationState,因此此启动流程将收集所需对手方的签名。这里的漏洞是bob发起了这个交易,但包含了aliceBankruptcyDeclarationState拥有的类型的输出。他不应该被允许这样做,因为应该只允许所有者签发,但在这种情况下,爱丽丝会因为要求签署 .BankruptcyDeclarationStateObligationState

这里有一个论点是,可以以这样一种方式编写流程,即爱丽丝会在签名之前检查交易以确保不包括某些状态,但我觉得这还不够。这需要开发人员和节点管理员对流程进行尽职调查,以确保其安全性。

相比之下,严格的合约命令约束会以我认为更安全的方式防止这些漏洞 - 因此仅在合约级别需要尽职调查,而不是每个开发人员编写消耗合约的流程。

在这方面,我正在寻找一些明确的指南,说明合同命令约束是否应该严格、放松,或者是否还有其他我错过的考虑因素。谢谢。

标签: corda

解决方案


正如您正确指出的那样,所有交易方共享相同的合同代码。这是他们之间唯一的约定。但是每一方都通过开发他/她自己的安全流程来为他/她的行为(签名)负责。书面流程的基础是在签署之前根据合约代码验证交易。谁会在不阅读/检查合同的情况下以数字或其他方式签署任何东西?我错过了什么吗?


推荐阅读