Корда: Получение ошибки - Инициатор CollectSignaturesFlow должен передать именно сеансы, необходимые для подписания транзакции - PullRequest
0 голосов
/ 30 января 2020

Я следую учебнику Corda , чтобы создать приложение Corda. Вместо того, чтобы создавать его в Kotlin, я встроил его в Java.

Я следовал инструкциям, приведенным в do c, и ниже мой класс CarIssueInitiator.

package com.template.flows;

import co.paralleluniverse.fibers.Suspendable;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSet;
import com.template.contracts.CarContract;
import com.template.states.CarState;
import net.corda.core.contracts.Command;
import net.corda.core.contracts.UniqueIdentifier;
import net.corda.core.flows.*;
import net.corda.core.identity.Party;
import net.corda.core.transactions.SignedTransaction;
import net.corda.core.transactions.TransactionBuilder;
import net.corda.core.utilities.ProgressTracker;
import net.corda.core.utilities.ProgressTracker.Step;

import java.util.List;
import java.util.stream.Collectors;

// ******************
// * Initiator flow *
// ******************
@InitiatingFlow
@StartableByRPC
public class CarIssueInitiator extends FlowLogic<SignedTransaction> {

    private final Party owningBank;
    private final Party holdingDealer;
    private final Party manufacturer;
    private final String vin;
    private final String licensePlateNumber;
    private final String make;
    private final String model;
    private final String dealershipLocation;

    private final Step GENERATING_TRANSACTION = new Step("Generating transaction based on new IOU.");
    private final Step VERIFYING_TRANSACTION = new Step("Verifying contract constraints.");
    private final Step SIGNING_TRANSACTION = new Step("Signing transaction with our private key.");
    private final Step GATHERING_SIGS = new Step("Gathering the counterparty's signature.") {
        @Override
        public ProgressTracker childProgressTracker() {
            return CollectSignaturesFlow.Companion.tracker();
        }
    };
    private final Step FINALISING_TRANSACTION = new Step("Obtaining notary signature and recording transaction.") {
        @Override
        public ProgressTracker childProgressTracker() {
            return FinalityFlow.Companion.tracker();
        }
    };


    private final ProgressTracker progressTracker = new ProgressTracker(
            GENERATING_TRANSACTION,
            VERIFYING_TRANSACTION,
            SIGNING_TRANSACTION,
            GATHERING_SIGS,
            FINALISING_TRANSACTION
    );
    public CarIssueInitiator(Party owningBank,
                             Party holdingDealer,
                             Party manufacturer,
                             String vin,
                             String licensePlateNumber,
                             String make,
                             String model,
                             String dealershipLocation){
        this.owningBank = owningBank;
        this.holdingDealer = holdingDealer;
        this.manufacturer = manufacturer;
        this.vin = vin;
        this.licensePlateNumber = licensePlateNumber;
        this.make = make;
        this.model = model;
        this.dealershipLocation = dealershipLocation;
    }

    @Override
    public ProgressTracker getProgressTracker() {
        return progressTracker;
    }

    @Suspendable
    @Override
    public SignedTransaction call() throws FlowException {
        // Initiator flow logic goes here.
        final Party notary = getServiceHub().getNetworkMapCache().getNotaryIdentities().get(0);

        // Stage 1.
        progressTracker.setCurrentStep(GENERATING_TRANSACTION);

        // Generate an unsigned transaction.
        Party me = getOurIdentity();

        CarState carState = new CarState(this.owningBank,
                this.holdingDealer,
                this.manufacturer,
                this.vin,
                this.licensePlateNumber,
                this.make,
                this.model,
                this.dealershipLocation,
                new UniqueIdentifier());

        final Command<CarContract.Commands.Issue> txCommand = new Command<CarContract.Commands.Issue>(new CarContract.Commands.Issue(),
                ImmutableList.of(carState.getOwningBank().getOwningKey(), carState.getHoldingDealer().getOwningKey(), carState.getManufacturer().getOwningKey()));

        final TransactionBuilder txBuilder = new TransactionBuilder(notary)
                .addOutputState(carState, CarContract.ID)
                .addCommand(txCommand);

        // Stage 2.
        progressTracker.setCurrentStep(VERIFYING_TRANSACTION);
        // Verify that the transaction is valid.
        txBuilder.verify(getServiceHub());

        //Stage 3
        progressTracker.setCurrentStep(SIGNING_TRANSACTION);
        // Sign the transaction.
        final SignedTransaction partSignedTx = getServiceHub().signInitialTransaction(txBuilder);

        // Stage 4.
        progressTracker.setCurrentStep(GATHERING_SIGS);

        // Send the state to the counterparty, and receive it back with their signature.

        List<FlowSession> sessions = carState.getParticipants().stream().map(a -> initiateFlow((Destination) a)).collect(Collectors.toList());
        //FlowSession session = initiateFlow(me);
        final SignedTransaction fullySignedTx = subFlow(
                new CollectSignaturesFlow(partSignedTx, sessions, ImmutableList.of(me.getOwningKey()), CollectSignaturesFlow.Companion.tracker()));

        // Stage 5.
        progressTracker.setCurrentStep(FINALISING_TRANSACTION);

        return subFlow(new FinalityFlow(fullySignedTx, sessions));
    }
}

Я развернул CordApp и запустил поток. Но я закончил с ошибкой ниже

java.lang.IllegalArgumentException: The Initiator of CollectSignaturesFlow must pass in exactly the sessions required to sign the transaction.
    at net.corda.core.flows.CollectSignaturesFlow.call(CollectSignaturesFlow.kt:164) ~[corda-core-4.3.jar:?]
    at net.corda.core.flows.CollectSignaturesFlow.call(CollectSignaturesFlow.kt:67) ~[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.CarIssueInitiator.call(CarIssueInitiator.java:129) ~[?:?]
    at com.template.flows.CarIssueInitiator.call(CarIssueInitiator.java:23) ~[?:?]
    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(Unknown Source) ~[?:1.8.0_192]
    at java.util.concurrent.FutureTask.run(Unknown Source) ~[?:1.8.0_192]
    at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.access$201(Unknown Source) ~[?:1.8.0_192]
    at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(Unknown Source) ~[?:1.8.0_192]
    at java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source) ~[?:1.8.0_192]
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source) ~[?:1.8.0_192]
    at net.corda.node.utilities.AffinityExecutor$ServiceAffinityExecutor$1$thread$1.run(AffinityExecutor.kt:63) ~[corda-node-4.3.jar:?]

Я не понимаю, что не так с кодом. Прошу вас, пожалуйста, помогите мне с этим.

ОБНОВЛЕНИЕ : с обновленным кодом, он работает для меня.

//Stage 3
        progressTracker.setCurrentStep(SIGNING_TRANSACTION);
        // Sign the transaction.
        final PublicKey ourSigningKey = getServiceHub().getMyInfo().getLegalIdentities().get(0).getOwningKey();
        final SignedTransaction partSignedTx = getServiceHub().signInitialTransaction(txBuilder, ourSigningKey);

        // Stage 4.
        progressTracker.setCurrentStep(GATHERING_SIGS);

        // Send the state to the counterparty, and receive it back with their signature.
        FlowSession HoldingDealerPartyFlow = initiateFlow(carState.getHoldingDealer());
        FlowSession ManufacturerPartyFlow = initiateFlow(carState.getManufacturer());

        final SignedTransaction fullySignedTx = subFlow(new CollectSignaturesFlow(
                partSignedTx,
                ImmutableSet.of(HoldingDealerPartyFlow, ManufacturerPartyFlow),
                ImmutableList.of(ourSigningKey))
        );

        // Stage 5.
        progressTracker.setCurrentStep(FINALISING_TRANSACTION);
        return subFlow(new FinalityFlow(fullySignedTx, ImmutableSet.of(HoldingDealerPartyFlow, ManufacturerPartyFlow)));

Ответы [ 2 ]

1 голос
/ 30 января 2020

Список подписавшихся в carState.getParticipants() (см. Код A) не совпадает со списком подписавшихся в ImmutableList CollectSignaturesFlow (см. Код B).

Код A: List<FlowSession> sessions = carState.getParticipants().stream().map(a -> initiateFlow((Destination) a)).collect(Collectors.toList());

Код B: final SignedTransaction fullySignedTx = subFlow( new CollectSignaturesFlow(partSignedTx, sessions, ImmutableList.of(me.getOwningKey()), CollectSignaturesFlow.Companion.tracker()));

В ImmutableList необходимо добавить carState.getOwningBank().getOwningKey(), carState.getHoldingDealer().getOwningKey(), carState.getManufacturer().getOwningKey()

EDITED Попробуйте следующий код из «Этапа 3» вперед

    //Stage 3
    progressTracker.setCurrentStep(SIGNING_TRANSACTION);
    // Sign the transaction.
    //final SignedTransaction partSignedTx = getServiceHub().signInitialTransaction(txBuilder);
    val ourSigningKey = serviceHub.myInfo.legalIdentities.first().owningKey
    val partSignedTx = serviceHub.signInitialTransaction(tx, ourSigningKey)


    // Stage 4.
    progressTracker.setCurrentStep(GATHERING_SIGS);
    // Send the state to the counterparty, and receive it back with their signature.
    //List<FlowSession> sessions = carState.getParticipants().stream().map(a -> initiateFlow((Destination) a)).collect(Collectors.toList());
    //FlowSession session = initiateFlow(me);
    //final SignedTransaction fullySignedTx = subFlow(
    //        new CollectSignaturesFlow(partSignedTx, sessions, ImmutableList.of(me.getOwningKey()), CollectSignaturesFlow.Companion.tracker()));

     val HoldingDealerPartyFlow = initiateFlow(carState.getHoldingDealer())
     val ManufacturerPartyFlow = initiateFlow(carState.getManufacturer())

    val fullySignedTx = subFlow(CollectSignaturesFlow(
         partSignedTx,
         setOf(HoldingDealerPartyFlow ManufacturerPartyFlow),
         listOf(ourSigningKey))
    )


    // Stage 5.
    progressTracker.setCurrentStep(FINALISING_TRANSACTION); 
    //return subFlow(new FinalityFlow(fullySignedTx, sessions));
    subFlow(FinalityFlow(fullySignedTx, setOf(HoldingDealerPartyFlow ManufacturerPartyFlow)))
    return fullySignedTx.tx.outRef<State>(0)
0 голосов
/ 30 января 2020

Вы должны вызывать initiateFlow () только для всех участников, кроме себя, чтобы ваш код мог выглядеть так (грамматика может быть неправильной, но показывает смысл):

List<FlowSession> sessions = (carState.getParticipants() - me).stream().map(a -> initiateFlow((Destination) a)).collect(Collectors.toList());
...