【发布时间】:2020-09-08 01:30:40
【问题描述】:
我正在构建一个需要多个 CorDapps 的应用程序;我们称它们为 LibCorDapp 和 AppCorDapp,其中 AppCorDapp 依赖于 LibCorDapp(就像 CorDapp 可能依赖于 Accounts或令牌 SDK)。
LibCorDapp - 合约
这个 CorDapp 的目的是定义一个状态和合约的对象模型,可以开箱即用,但也可以派生出更明确的状态和合约类型。
build.gradle
cordapp {
targetPlatformVersion cordapp_platform_version
minimumPlatformVersion cordapp_platform_version
contract {
name cordapp_contract_name
vendor cordapp_vendor_name
licence cordapp_license
versionId cordapp_version_id
}
signing {
enabled = cordapp_signing_enabled
}
}
dependencies {
implementation "$kotlin_group:kotlin-stdlib-jdk8:$kotlin_version"
cordaCompile "$corda_group:corda-core:$corda_release_version"
testRuntimeOnly "$junit_group:junit-jupiter-engine:$junit_version"
testImplementation "$junit_group:junit-jupiter-api:$junit_version"
testImplementation "$kotlin_group:kotlin-test:$kotlin_version"
testImplementation "$corda_group:corda-node-driver:$corda_release_version"
}
示例状态
package com.example.libcordapp.contract
@BelongsToContract(ExampleContract::class)
open class ExampleState<T : Any>(
override val participants: List<AbstractParty> = emptyList(),
val value: T
) : ContractState { ... }
合同示例
package com.example.libcordapp.contract
open class ExampleContract {
final override fun verify(tx: LedgerTransaction) { ... }
protected open fun onVerifyCreate(tx: LedgerTransaction, signers: Set<PublicKey>) = Unit
}
注意ExampleState 和ExampleContract 之间的关系。它们都是open,ExampleContract 包含一个可覆盖的函数,允许派生类在创建时指定额外的合约逻辑。
LibCorDapp - 工作流程
这个 CorDapp 的目的是定义允许创建、更新和使用示例状态的流程。这些流程应该也适用于派生自 ExampleState 和 ExampleContract 的状态和合约。
build.gradle
cordapp {
targetPlatformVersion cordapp_platform_version
minimumPlatformVersion cordapp_platform_version
workflow {
name cordapp_workflow_name
vendor cordapp_vendor_name
licence cordapp_license
versionId cordapp_version_id
}
signing {
enabled = cordapp_signing_enabled
}
}
dependencies {
implementation "$kotlin_group:kotlin-stdlib-jdk8:$kotlin_version"
cordaCompile "$corda_group:corda-core:$corda_release_version"
cordapp project(":libcordapp-contract")
testRuntimeOnly "$junit_group:junit-jupiter-engine:$junit_version"
testImplementation "$junit_group:junit-jupiter-api:$junit_version"
testImplementation "$kotlin_group:kotlin-test:$kotlin_version"
testImplementation "$corda_group:corda-node-driver:$corda_release_version"
}
示例流程
package com.example.libcordapp.workflow
class ExampleFlow(val state: ExampleState) : FlowLogic<SignedTransaction>() {
@Suspendable
override fun call(): SignedTransaction {
val tx = with(TransactionBuilder(notary)) {
addOutputState(state)
addCommand(ExampleContract.Issue, signers)
}
}
}
请注意,我没有明确定义输出状态的合约 ID,因为它应该在运行时为每个合约/状态对确定。
AppCorDapp - 合约
此 CorDapp 的目的是演示一个使用 LibCorDapp、创建和测试派生状态和合约的应用程序示例。
build.gradle
cordapp {
targetPlatformVersion cordapp_platform_version
minimumPlatformVersion cordapp_platform_version
contract {
name "Test CorDapp Contract"
vendor cordapp_vendor_name
licence cordapp_license
versionId cordapp_version_id
}
signing {
enabled = cordapp_signing_enabled
}
}
dependencies {
implementation "$kotlin_group:kotlin-stdlib-jdk8:$kotlin_version"
implementation "$corda_group:corda-core:$corda_release_version"
cordapp project(":libcordapp-contract")
testRuntimeOnly "$junit_group:junit-jupiter-engine:$junit_version"
testImplementation "$junit_group:junit-jupiter-api:$junit_version"
testImplementation "$kotlin_group:kotlin-test:$kotlin_version"
testImplementation "$corda_group:corda-node-driver:$corda_release_version"
}
问候状态
package com.example.appcordapp.contract
@BelongsToContract(GreetingContract::class)
class GreetingState(
participants: List<AbstractParty> = emptyList()
value: String = "Hello, World!"
) : ExampleState<String>(participants, value)
问候合同
package com.example.appcordapp.contract
class GreetingContract : ExampleContract {
override fun onVerifyCreate(tx: LedgerTransaction, signers: Set<PublicKey>) = requireThat { ... }
}
请注意GreetingContract 扩展ExampleContract 和GreetingState 扩展ExampleState 以及将GreetingContract 定义为相关合同,因此在使用ExampleFlow 创建GreetingState 时,它应该选择此合同。
AppCorDapp - 工作流 模块中实际上没有定义任何流,因为我明确想测试我是否可以将ExampleFlow 与派生的状态/合同对一起使用。
测试与问题
对于我的测试,我定义了以下 cordapps:
cordappsForAllNodes = listOf(
TestCordapp.findCordapp("com.example.libcordapp.contract"),
TestCordapp.findCordapp("com.example.libcordapp.workflow"),
TestCordapp.findCordapp("com.example.appcordapp.contract")
)
在尝试使用ExampleFlow 创建GreetingClaim 时...
ExampleFlow(GreetingClaim(participants = listOf(partyA)))
...我得到以下异常:
java.lang.IllegalArgumentException: 在类路径 [/.../libcordapp-contract-0.1.jar, /.../libcordapp-workflow 上有多个包含 com.example.appcordapp.contract 包的 CorDapp -0.1.jar]。指定一个 CorDapp 唯一的包名。
我假设这要么归结为 gradle,要么与我使用派生状态和合同这一事实有关?
【问题讨论】:
-
我认为派生合约导致了这个问题。