Corda中如何实现原子多方交易?
How to achieve atomic multi-party transactions in Corda?
假设我有 parties A, B, and Z
。
并指出 S1 between A and Z
和 S2 between B and Z
。 A 对 S2 和 B 对 S1 都不是私有的。
我希望 Z 原子地修改 S1 和 S2,这样在 'transaction' 进行时,A 和 B 都不能对 S1 或 S2 进行更新,分别
目前思路是:Z先获取S1和S2的软锁,然后发起流程修改S1,A为交易对手,S2修改B为交易对手。然后,解除S1和S2的软锁。
我为状态编写合约,修改命令需要Z签名。
至关重要的是,如果 A 或 B 试图修改 S1 或 S2,如果 Z 在 Z 的第一笔交易正在进行时收到该修改的接受者流,它只会拒绝签名。但是我必须完全实施吗?获取 S1 和 S2 上的软锁不会阻止接受器流对 S1 和 S2 做任何事情吗?
或者有更好的方法吗?
在其他答案的基础上,这是使用 soft-locking API 来防止节点同时进入涉及两个状态的交易的一种方法:
@InitiatingFlow
@StartableByRPC
class AtomicFlow(val stateRefToSpend: StateRef, val stateRefToLock: StateRef) : FlowLogic<Unit>() {
@Suspendable
override fun call() {
try {
serviceHub.vaultService.softLockReserve(runId.uuid, NonEmptySet.of(stateRefToSpend, stateRefToLock))
} catch (e: StatesNotAvailableException) {
logger.error("A transaction is already underway using S2.")
return
}
val stateToSpend = serviceHub.loadState(stateRefToSpend)
// Continue with transaction...
}
}
是的,非常正确。如果S1和S2是multi-party状态,分别需要{A,Z}和{B,Z}签名,那么Z可以和公证人一起充当锁管理器。
软锁API如果拿不到锁就会抛出。因此,您只需在流程开始时为状态添加预留。如果另一个流并行获取锁,您将抛出并且交易对手会找出原因。
将来我们可能会将软锁定与 TransactionBuilder 集成,因此向 TransactionBuilder 添加状态的行为会自动软锁定它,如果不能则抛出。
只是为了让 soft-locking
更加清晰
Soft-locking 是一种单节点机制(当前),用于防止多个流花费/修改相同的状态。 没有与其他节点(可能具有相同的共享状态)的协调。
正如 Mike 在上面指出的那样,公证人是最终唯一性(double-spend 预防)协调员。因此,在您上面的场景中,竞争条件(例如 A 和 Z 试图同时更改 S1;B 和 Z 试图同时更改 S2)最终将由 Notary 服务解决。
总而言之,soft-locking 是一种本地节点功能,可通过早期检测 double-spend/modification 尝试来提高性能,而无需公证人。在 multi-node(分布式状态 spending/modifying 场景)公证人是协调者(和共享状态的双重 spend/modification 检测器)。
假设我有 parties A, B, and Z
。
并指出 S1 between A and Z
和 S2 between B and Z
。 A 对 S2 和 B 对 S1 都不是私有的。
我希望 Z 原子地修改 S1 和 S2,这样在 'transaction' 进行时,A 和 B 都不能对 S1 或 S2 进行更新,分别
目前思路是:Z先获取S1和S2的软锁,然后发起流程修改S1,A为交易对手,S2修改B为交易对手。然后,解除S1和S2的软锁。
我为状态编写合约,修改命令需要Z签名。
至关重要的是,如果 A 或 B 试图修改 S1 或 S2,如果 Z 在 Z 的第一笔交易正在进行时收到该修改的接受者流,它只会拒绝签名。但是我必须完全实施吗?获取 S1 和 S2 上的软锁不会阻止接受器流对 S1 和 S2 做任何事情吗?
或者有更好的方法吗?
在其他答案的基础上,这是使用 soft-locking API 来防止节点同时进入涉及两个状态的交易的一种方法:
@InitiatingFlow
@StartableByRPC
class AtomicFlow(val stateRefToSpend: StateRef, val stateRefToLock: StateRef) : FlowLogic<Unit>() {
@Suspendable
override fun call() {
try {
serviceHub.vaultService.softLockReserve(runId.uuid, NonEmptySet.of(stateRefToSpend, stateRefToLock))
} catch (e: StatesNotAvailableException) {
logger.error("A transaction is already underway using S2.")
return
}
val stateToSpend = serviceHub.loadState(stateRefToSpend)
// Continue with transaction...
}
}
是的,非常正确。如果S1和S2是multi-party状态,分别需要{A,Z}和{B,Z}签名,那么Z可以和公证人一起充当锁管理器。
软锁API如果拿不到锁就会抛出。因此,您只需在流程开始时为状态添加预留。如果另一个流并行获取锁,您将抛出并且交易对手会找出原因。
将来我们可能会将软锁定与 TransactionBuilder 集成,因此向 TransactionBuilder 添加状态的行为会自动软锁定它,如果不能则抛出。
只是为了让 soft-locking
更加清晰Soft-locking 是一种单节点机制(当前),用于防止多个流花费/修改相同的状态。 没有与其他节点(可能具有相同的共享状态)的协调。
正如 Mike 在上面指出的那样,公证人是最终唯一性(double-spend 预防)协调员。因此,在您上面的场景中,竞争条件(例如 A 和 Z 试图同时更改 S1;B 和 Z 试图同时更改 S2)最终将由 Notary 服务解决。
总而言之,soft-locking 是一种本地节点功能,可通过早期检测 double-spend/modification 尝试来提高性能,而无需公证人。在 multi-node(分布式状态 spending/modifying 场景)公证人是协调者(和共享状态的双重 spend/modification 检测器)。