在Corda帐户中找不到匿名方(DLC2iDbLTxfABXk2UgFJzej8RbX6hUQuCjYBDJATYjYAJW)错误

时间:2019-12-12 11:36:19

标签: corda

在我的cordapp中使用帐户net.corda.core.CordaRuntimeException:java.lang.IllegalArgumentException:我找不到流中的一个错误:找不到匿名方(DLBBYFJYhpPQXEMcTZtuzkg8ixptu92L3dqiN4boD1o2FN) 此错误来自“最终确定流程”行

这是错误日志

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));

进入源代码后,错误似乎来自此--->

@Throws(IllegalArgumentException::class)
fun groupAbstractPartyByWellKnownParty(serviceHub: ServiceHub, parties: Collection<AbstractParty>, ignoreUnrecognisedParties: Boolean): Map<Party, List<AbstractParty>> {
    val partyToPublicKey: Iterable<Pair<Party, AbstractParty>> = parties.mapNotNull {
        (serviceHub.identityService.wellKnownPartyFromAnonymous(it) ?: if (ignoreUnrecognisedParties) return@mapNotNull null else throw IllegalArgumentException("Could not find Party for $it")) to it
    }
    return partyToPublicKey.toMultiMap()
}

我有类似的流程,但是没有输入状态在起作用。

州级:

private PublicKey borrower;
private PublicKey lender;
private float amount;
private float creditScore;
private String status;
private final UniqueIdentifier linearId;

仅供参考,在这种状态下,我也为借款人和贷方使用了PublicKey数据类型

仅供参考,该流在不使用输入状态的情况下工作正常 帐户创建流程

    @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));

1 个答案:

答案 0 :(得分:0)

出现此错误的原因是,“确定性”流程正在查看您的输出状态和输入状态,并从中检索参与者。

然后尝试通过公钥将这些参与者分解为各方。

如果该节点在出现错误之前尚未看到那些公钥,则会抛出该错误。

由于问题中只有代码片段,因此不清楚导致问题的原因。

但是,以下示例将复制该问题:

LongByReference

如果您在测试中运行此流程(kotlin仅仅是因为我在现有项目中进行了测试),则会收到错误消息:

        Observable
            .FromEventPattern<EventHandler, EventArgs>(_ => SystemEvents.DisplaySettingsChanged += _, _ => SystemEvents.DisplaySettingsChanged -= _)
            .Select(_ => SystemParameters.WorkArea)
            .Do(_ =>
            {
                Left = _.Right - Width;
                Top = _.Bottom - Height;
            })
            .Subscribe();

但是,如果您更改了这两行:

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
//
 }

以便从同一节点请求密钥,流程将运行并且测试将通过。

@Test
fun `Find party`() {
    val borrowerAccountService = borrowerNode.services.cordaService(KeyManagementBackedAccountService::class.java)
    val lenderAccountService = lenderNode.services.cordaService(KeyManagementBackedAccountService::class.java)

    val borrowerAccount = borrowerAccountService.createAccount("Borrower-Account").getOrThrow().state.data
    val lenderAccount = lenderAccountService.createAccount("Lender-Account").getOrThrow().state.data
    network.runNetwork()

    borrowerAccountService.shareAccountInfoWithParty(borrowerAccount.identifier.id, lenderNode.info.legalIdentities[0])
    lenderAccountService.shareAccountInfoWithParty(lenderAccount.identifier.id, borrowerNode.info.legalIdentities[0])
    network.runNetwork()

    val borrowerPartyFuture = borrowerNode.startFlow(RequestKeyForAccount(borrowerAccount))
    val lenderPartyFuture = lenderNode.startFlow(RequestKeyForAccount(lenderAccount))
    network.runNetwork()
    val borrowerParty = borrowerPartyFuture.getOrThrow()
    val lenderParty = lenderPartyFuture.getOrThrow()

    val newLoanFuture = lenderNode.startFlow(SaveLoanFlow(borrowerParty, lenderParty, 2F, 4F))
    network.runNetwork()

    val savedLoan = newLoanFuture.getOrThrow()
    Assert.notEmpty(savedLoan.tx.outputStates)
}
}

原因是现在贷方知道两个帐户的密钥。

因此在您未显示的代码中,您遇到了类似的问题,因为两个节点上的帐户密钥均不可用。

您似乎在问题中发布的流程之前运行了另一个流程,因为您执行了保管库查找并将其用作输入状态。

其中一个节点上可能不存在来自保存状态的键之一。

出于(无法预见?)设计的原因,当将状态保存到流中时,不会保存生成的键,因此必须运行额外的流以确保所有生成的键都已同步。

您可以在未显示流程的末尾作为子流程来执行此操作,这可能会解决问题。

    val borrowerPartyFuture = borrowerNode.startFlow(RequestKeyForAccount(borrowerAccount))
    val lenderPartyFuture = lenderNode.startFlow(RequestKeyForAccount(lenderAccount))

跟踪this issue以获取更多信息。