在corda帐户中找不到匿名(DLC2IDBLTXABXK2UGFJZEJ8RBX6HUQUCJYBDJATYJYAJW)错误的参与方
在我的cordapp中使用帐户net.corda.core.CordaRuntimeException:java.lang.IllegalArgumentException:找不到匿名的参与方(DLBBYFJYHPQXemCtZKG8IXPTU92L3DQIN4BOD1O2FN)时,我在其中一个流中遇到此错误 此错误出现在最终性流程线上 这是错误日志在corda帐户中找不到匿名(DLC2IDBLTXABXK2UGFJZEJ8RBX6HUQUCJYBDJATYJYAJW)错误的参与方,corda,Corda,在我的cordapp中使用帐户net.corda.core.CordaRuntimeException:java.lang.IllegalArgumentException:找不到匿名的参与方(DLBBYFJYHPQXemCtZKG8IXPTU92L3DQIN4BOD1O2FN)时,我在其中一个流中遇到此错误 此错误出现在最终性流程线上 这是错误日志 java.lang.IllegalArgumentException: Could not find Party for Anonymous(DL
java.lang.IllegalArgumentException: Could not find Party for Anonymous(DLKiQpwdw3E7CewLhUatjRpKvCMkHDhEoEYXfAUrp33z7)
at net.corda.core.identity.IdentityUtils.groupAbstractPartyByWellKnownParty(IdentityUtils.kt:47) ~[corda-core-4.3.jar:?]
at net.corda.core.identity.IdentityUtils.groupAbstractPartyByWellKnownParty(IdentityUtils.kt:63) ~[corda-core-4.3.jar:?]
at net.corda.core.flows.FinalityFlow.extractExternalParticipants(FinalityFlow.kt:224) ~[corda-core-4.3.jar:?]
at net.corda.core.flows.FinalityFlow.call(FinalityFlow.kt:134) ~[corda-core-4.3.jar:?]
at net.corda.core.flows.FinalityFlow.call(FinalityFlow.kt:39) ~[corda-core-4.3.jar:?]
at net.corda.node.services.statemachine.FlowStateMachineImpl.subFlow(FlowStateMachineImpl.kt:330) ~[corda-node-4.3.jar:?]
at net.corda.core.flows.FlowLogic.subFlow(FlowLogic.kt:326) ~[corda-core-4.3.jar:?]
at com.template.flows.LoanTransferFlow.call(LoanTransferFlow.java:129) ~[?:?]
at com.template.flows.LoanTransferFlow.call(LoanTransferFlow.java:29) ~[?:?]
at net.corda.node.services.statemachine.FlowStateMachineImpl.run(FlowStateMachineImpl.kt:270) ~[corda-node-4.3.jar:?]
at net.corda.node.services.statemachine.FlowStateMachineImpl.run(FlowStateMachineImpl.kt:46) ~[corda-node-4.3.jar:?]
at co.paralleluniverse.fibers.Fiber.run1(Fiber.java:1092) ~[quasar-core-0.7.10-jdk8.jar:0.7.10]
at co.paralleluniverse.fibers.Fiber.exec(Fiber.java:788) ~[quasar-core-0.7.10-jdk8.jar:0.7.10]
at co.paralleluniverse.fibers.RunnableFiberTask.doExec(RunnableFiberTask.java:100) ~[quasar-core-0.7.10-jdk8.jar:0.7.10]
at co.paralleluniverse.fibers.RunnableFiberTask.run(RunnableFiberTask.java:91) ~[quasar-core-0.7.10-jdk8.jar:0.7.10]
at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511) ~[?:1.8.0_212]
at java.util.concurrent.FutureTask.run(FutureTask.java:266) ~[?:1.8.0_212]
at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.access$201(ScheduledThreadPoolExecutor.java:180) ~[?:1.8.0_212]
at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:293) ~[?:1.8.0_212]
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149) ~[?:1.8.0_212]
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624) ~[?:1.8.0_212]
at net.corda.node.utilities.AffinityExecutor$ServiceAffinityExecutor$1$thread$1.run(AffinityExecutor.kt:63) ~[corda-node-4.3.jar:?]
该流处于输入状态&3输出状态
以下是流程代码:
@InitiatingFlow
@StartableByRPC
public class LoanTransferFlow extends FlowLogic<SignedTransaction> {
final AccountInfo borrower;
final AccountInfo lender;
UniqueIdentifier loanId = null;
StateAndRef<InfoState> inputBorrowerState = null;
private final static Logger logger = LoggerFactory.getLogger(LoanTransferFlow.class);
public LoanTransferFlow(AccountInfo borrower, AccountInfo lender, UniqueIdentifier loanId, StateAndRef<InfoState> inputBorrowerState) {
this.borrower = borrower;
this.lender = lender;
this.loanId = loanId;
this.inputBorrowerState = inputBorrowerState;
}
@Suspendable
@Override
public SignedTransaction call() throws FlowException {
final Party notary = getServiceHub().getNetworkMapCache().getNotaryIdentities().get(0);
List<StateAndRef<InfoState>> matchingLenderStates = null;
StateAndRef<InfoState> inputInfoLenderState = null;
StateAndRef<LoanState> inputLoanState = null;
//
// PublicKey myKey = subFlow(new RequestKeyForAccount(lender.getHost(), lender.getIdentifier().getId())).getOwningKey();
// PublicKey borrowerKey = subFlow(new RequestKeyForAccount(borrower.getHost(), borrower.getIdentifier().getId())).getOwningKey();
try {
Vault.Page<InfoState> lenderStateresults = (Vault.Page<InfoState>) subFlow(new CheckAccountInfoFlow(lender.getName()));
matchingLenderStates = lenderStateresults.getStates();
} catch (Exception e) {
throw new FlowException(e);
}
if ((matchingLenderStates == null) || (matchingLenderStates.isEmpty())) {
throw new FlowException("No Initial Borrower State Exists");
} else {
inputInfoLenderState = matchingLenderStates.get(matchingLenderStates.size() - 1);
}
QueryCriteria criteriaForLoanVault = new QueryCriteria.LinearStateQueryCriteria(
null,
ImmutableList.of(loanId),
Vault.StateStatus.UNCONSUMED,
null);
List<StateAndRef<LoanState>> matchingLoanStates = getServiceHub().getVaultService().queryBy(LoanState.class, criteriaForLoanVault).getStates();
if ((matchingLoanStates == null) || (matchingLoanStates.isEmpty())) {
throw new FlowException("No Initial Loan State Exists");
} else {
inputLoanState = matchingLoanStates.get(0);
}
subFlow(new ShareStateAndSyncAccounts(inputLoanState, borrower.getHost()));
subFlow(new ShareStateAndSyncAccounts(inputLoanState, lender.getHost()));
PublicKey myKey = inputLoanState.getState().getData().getLender();
PublicKey borrowerKey = inputLoanState.getState().getData().getBorrower();
logger.info("inputState" + inputLoanState.getState().getData().getBorrower() + inputLoanState.getState().getData().getLender());
logger.info("mykey" + myKey);
logger.info("borrowerKey" + borrowerKey);
float updatedBorrowerCreditscore = inputLoanState.getState().getData().getCreditScore() - 15;
float updatedLenderCreditscore = inputInfoLenderState.getState().getData().getCreditScore() + 30;
float amount = inputLoanState.getState().getData().getAmount();
float borrowerBalance = inputBorrowerState.getState().getData().getBalance();
float lenderBalance = inputInfoLenderState.getState().getData().getBalance();
if (amount > lenderBalance) {
throw new FlowException("Insufficient Lender Balance");
}
float updatedBorrowerBalance = borrowerBalance + amount;
float updatedLenderBalance = lenderBalance - amount;
final Command<LendingContract.Commands.Transfer> command = new Command<LendingContract.Commands.Transfer>(new LendingContract.Commands.Transfer(), Arrays.asList(myKey, borrowerKey));
LoanState outputLoanState = new LoanState(borrowerKey, myKey, amount, updatedBorrowerCreditscore, "approved", new UniqueIdentifier());
logger.info("outputState" + outputLoanState.getLender() + outputLoanState.getBorrower());
InfoState outputBorrowerState = new InfoState(new AnonymousParty(borrowerKey), updatedBorrowerCreditscore, updatedBorrowerBalance, new UniqueIdentifier());
InfoState outputLenderState = new InfoState(new AnonymousParty(myKey), updatedLenderCreditscore, updatedLenderBalance, new UniqueIdentifier());
TransactionBuilder txBuilder = new TransactionBuilder(notary);
txBuilder.addInputState(inputLoanState);
txBuilder.addCommand(command);
txBuilder.addOutputState(outputBorrowerState, LendingContract.ID);
txBuilder.addOutputState(outputLenderState, LendingContract.ID);
txBuilder.addOutputState(outputLoanState, LendingContract.ID);
txBuilder.verify(getServiceHub());
SignedTransaction signedInitialTransaction = getServiceHub().signInitialTransaction(txBuilder, Arrays.asList(getOurIdentity().getOwningKey(), myKey));
FlowSession counterPartySession = initiateFlow(borrower.getHost());
List<? extends TransactionSignature> accountToMoveToSignature = subFlow(new CollectSignatureFlow(signedInitialTransaction, counterPartySession, borrowerKey));
SignedTransaction fullySignedTx = signedInitialTransaction.withAdditionalSignature(accountToMoveToSignature.get(0));
return subFlow(new FinalityFlow(fullySignedTx));
FYI还使用了该州借款人和贷款人的公钥数据类型
仅供参考,流程在不使用输入状态的情况下工作正常
账户创建流程
@Suspendable
override fun call(): AccountInfo {
//Create a new account
try {
val existingAccount = accountService.accountInfo(name = acctName)
if (existingAccount.size >= 1) {
throw FlowException("Account Already Exists")
}
val newAccount = accountService.createAccount(name = acctName).toCompletableFuture().getOrThrow()
val acct = newAccount.state.data
return acct
} catch (e: Exception) {
throw FlowException(e)
}
}
帐户共享流
@Suspendable
override fun call(): Boolean {
//Create a new account
val AllmyAccounts = accountService.ourAccounts()
val SharedAccount = AllmyAccounts.single { it.state.data.name == acctNameShared }.state.data.identifier.id
accountService.shareAccountInfoWithParty(SharedAccount,shareTo)
return true
}
供参考-有两个帐户都位于不同的节点上
同时添加输入状态流
public LoanRequestFlow(AccountInfo borrower, AccountInfo lender, float amount) {
this.borrower = borrower;
this.amount = amount;
this.lender = lender;
}
private final ProgressTracker progressTracker = new ProgressTracker();
private final static Logger logger = LoggerFactory.getLogger(LoanRequestFlow.class);
@Override
public ProgressTracker getProgressTracker() {
return progressTracker;
}
@Suspendable
@Override
public SignedTransaction call() throws FlowException {
final Party notary = getServiceHub().getNetworkMapCache().getNotaryIdentities().get(0);
List<StateAndRef<InfoState>> matchingBorrowerStates = null;
StateAndRef<InfoState> inputInfoBorrowerState = null;
PublicKey myKey = subFlow(new NewKeyForAccount(borrower.getIdentifier().getId())).getOwningKey();
PublicKey lenderKey = subFlow(new RequestKeyForAccount(lender)).getOwningKey();
try {
Vault.Page<InfoState> borrowerStateresults = (Vault.Page<InfoState>) subFlow(new CheckAccountInfoFlow(borrower.getName()));
matchingBorrowerStates = borrowerStateresults.getStates();
} catch (Exception e) {
throw new FlowException(e);
}
if ((matchingBorrowerStates == null) || (matchingBorrowerStates.isEmpty())) {
throw new FlowException("No Initial Borrower State Exists");
} else {
inputInfoBorrowerState = matchingBorrowerStates.get(matchingBorrowerStates.size() - 1);
}
final Command<LendingContract.Commands.Request> command = new Command<LendingContract.Commands.Request>(new LendingContract.Commands.Request(), Arrays.asList(myKey, lenderKey));
LoanState loanOutputState = new LoanState(myKey, lenderKey, amount, inputInfoBorrowerState.getState().getData().getCreditScore(), "pending", new UniqueIdentifier());
TransactionBuilder txBuilder = new TransactionBuilder(notary);
txBuilder.addCommand(command);
txBuilder.addOutputState(loanOutputState, LendingContract.ID);
txBuilder.verify(getServiceHub());
SignedTransaction signedInitialTransaction = getServiceHub().signInitialTransaction(txBuilder, Arrays.asList(getOurIdentity().getOwningKey(), myKey));
FlowSession counterPartySession = initiateFlow(lender.getHost());
List<? extends TransactionSignature> accountToMoveToSignature = subFlow(new CollectSignatureFlow(signedInitialTransaction, counterPartySession, lenderKey));
SignedTransaction fullySignedTx = signedInitialTransaction.withAdditionalSignature(accountToMoveToSignature.get(0));
return subFlow(new FinalityFlow(fullySignedTx));
公共贷款请求流(账户信息借款人、账户信息贷款人、浮动金额){
this.借款人=借款人;
这个。金额=金额;
this.leader=贷方;
}
private final ProgressTracker ProgressTracker=新ProgressTracker();
私有最终静态记录器Logger=LoggerFactory.getLogger(LoanRequestFlow.class);
@凌驾
公共ProgressTracker getProgressTracker(){
返回进程跟踪器;
}
@暂停
@凌驾
public SignedTransaction调用()引发流异常{
最终参与方公证人=getServiceHub().getNetworkMapCache().getNotaryIdentities().get(0);
列表匹配借款状态=null;
StateAndRef InputFoFrooderState=null;
PublicKey myKey=subFlow(NewKeyForAccount(forrower.getIdentifier().getId()).getOwningKey();
PublicKey-lenderKey=子流(新的RequestKeyForAccount(贷方)).getOwningKey();
试一试{
Vault.Page借用器StateResults=(Vault.Page)子流(新的CheckAccountInfoFlow(借用器.getName());
matchingBorrowerStates=borrowerStateresults.getStates();
}捕获(例外e){
抛出新的FlowException(e);
}
if((matchingBorrowerStates==null)| |(matchingBorrowerStates.isEmpty()){
抛出新的FlowException(“不存在初始借款人状态”);
}否则{
InputFoFrooderState=MatchingFrooderStates.get(MatchingFrooderStates.size()-1);
}
final Command Command=new命令(new LendingContract.Commands.Request(),Arrays.asList(myKey,lenderKey));
LoanState loanOutputState=新的LoanState(myKey,lenderKey,amount,inputinfobrowerstate.getState().getData().getCreditScore(),“待定”,新的UniqueIdentifier());
TransactionBuilder txBuilder=新TransactionBuilder(公证人);
txBuilder.addCommand(命令);
txBuilder.addOutputState(loanOutputState,LendingContract.ID);
验证(getServiceHub());
SignedTransaction SignedInitialtTransaction=getServiceHub().signInitialTransaction(txBuilder,Arrays.asList(GetTouridenty().getOwningKey(),myKey));
FlowSession counterPartySession=initiateFlow(leander.getHost());
List出现此错误的原因是,最终流正在查看您的输出状态和输入状态,并从中检索参与者
然后,它尝试通过公钥将这些参与者解析为各方
如果节点在抛出您看到的错误之前没有看到这些公钥
因为问题中只有代码片段,所以不太清楚问题的起因
但是,以下示例将复制该问题:
public class SaveLoanFlow extends FlowLogic<SignedTransaction> {
private AnonymousParty borrower;
private AnonymousParty lender;
private float amount;
private float creditScore;
public SaveLoanFlow(AnonymousParty borrower, AnonymousParty lender, float amount, float creditScore) {
this.borrower = borrower;
this.lender = lender;
this.amount = amount;
this.creditScore = creditScore;
}
@Suspendable
@Override
public SignedTransaction call() throws FlowException {
final Party notary = getServiceHub().getNetworkMapCache().getNotaryIdentities().get(0);
List<PublicKey> signingPubKeys = Arrays.asList(getOurIdentity().getOwningKey());
TransactionBuilder txBuilder = new TransactionBuilder(notary);
LoanState loanState = new LoanState(borrower, lender, amount, creditScore, "NEW", new UniqueIdentifier());
txBuilder.addOutputState(loanState);
txBuilder.addCommand(new LendingContract.Commands.Transfer(), signingPubKeys);
SignedTransaction signedInitialTransaction = getServiceHub().signInitialTransaction(txBuilder, signingPubKeys);
return subFlow(new FinalityFlow(signedInitialTransaction));
}
}
public class LendingContract implements Contract {
public static final Party ID = null;
@Override
public void verify(@NotNull LedgerTransaction tx) throws IllegalArgumentException {
}
/**
* This contract only implements one command, Transfer.
*/
public interface Commands extends CommandData {
class Transfer implements Commands {}
}
}
@BelongsToContract(LendingContract.class)
public class LoanState implements LinearState {
private AnonymousParty borrower;
private AnonymousParty lender;
private float amount;
private float creditScore;
private String status;
private UniqueIdentifier linearId;
public LoanState(AnonymousParty borrower, AnonymousParty lender, float amount, float creditScore, String status, UniqueIdentifier linearId) {
this.borrower = borrower;
this.lender = lender;
this.amount = amount;
this.creditScore = creditScore;
this.status = status;
this.linearId = linearId;
}
@NotNull
@Override
public List<AbstractParty> getParticipants() {
return ImmutableList.of(borrower, lender);
}
@NotNull
@Override
public UniqueIdentifier getLinearId() {
return linearId;
}
//
//other getters/setters
//
}
但是,如果更改这两行:
val borrowerPartyFuture = borrowerNode.startFlow(RequestKeyForAccount(borrowerAccount))
val lenderPartyFuture = lenderNode.startFlow(RequestKeyForAccount(lenderAccount))
因此,从流将运行且测试将通过的同一节点请求密钥
val borrowerPartyFuture = lenderNode.startFlow(RequestKeyForAccount(borrowerAccount))
val lenderPartyFuture = lenderNode.startFlow(RequestKeyForAccount(lenderAccount))
原因是现在贷款人已经知道这两个账户的密钥
因此,在代码中您没有显示的某个地方,您有一个类似的问题,即帐户密钥在两个节点上都不可用
看起来您在问题中发布的流之前运行了另一个流,因为您执行了vault查找并将其用作输入状态
其中一个节点上可能不存在保存状态中的一个密钥
出于(不可预见的?)设计原因,当您在流中保存状态时,生成的密钥不会保存,您必须运行额外的流以确保所有生成的密钥同步
您可以在未显示的流末尾作为子流执行此操作,它可能会解决问题
//If you don't do this you can't lookup accounts by PublicKey on the other host
subFlow(ShareStateAndSyncAccounts(state, lenderAccount.state.data.host))
追踪更多信息。确保您正在使用Corda 4.3.Yup,使用它。.帐户是在同一个节点上还是在不同的节点上?如果它们在不同的节点上,您是否与每个节点共享了帐户?是的,共享了帐户,有一个与此类似的流在不同的节点上工作,即不使用输入状态Viraz,有太多个uch正在您的流程中进行;很难找出导致错误的原因。谢谢@opticyclic,是的,我在一个只有一个帐户的状态下对该帐户进行了vault查询,但我正在以前的流程中生成新密钥,该流程在没有输入状态的情况下工作,因此您建议我在这里做什么。?早些时候我与您共享了一个帐户一个节点,但现在我与另一个节点共享了计数器帐户,但我仍然遇到相同的问题。是否这样做(ShareStateAndSyncAccounts)在这两个帐户的流程中,但仍然不起作用。相同的错误您说您正在执行Share State和SyncAccounts,但您发布的新代码清楚地表明您没有。我建议将此答案中的代码复制到您的项目中,运行测试以查看错误,然后进行更改以查看修复程序。然后您可以看到它在哪里工作适用于您的代码。在GitHub上创建一个复制该问题的演示项目也会使您更容易获得帮助。您还没有看到流代码,请查看子流(new ShareStateAndSyncAccounts(inputLoanState,borrower.getHost());子流(new ShareStateAndSyncAccounts(inputLoanState,Leader.getHost());
val borrowerPartyFuture = borrowerNode.startFlow(RequestKeyForAccount(borrowerAccount))
val lenderPartyFuture = lenderNode.startFlow(RequestKeyForAccount(lenderAccount))
val borrowerPartyFuture = lenderNode.startFlow(RequestKeyForAccount(borrowerAccount))
val lenderPartyFuture = lenderNode.startFlow(RequestKeyForAccount(lenderAccount))
//If you don't do this you can't lookup accounts by PublicKey on the other host
subFlow(ShareStateAndSyncAccounts(state, lenderAccount.state.data.host))