Hello World Tutorial issue


(Erhan S) #1

Hi,
I am trying to run hello world using Java. (https://docs.corda.net/hello-world-introduction.html). Verification at IOUContract fails ,when I start a flow on NodeA by:

start IOUFlow arg0: 99, arg1: “NodeB”

Because there is only NodeA’s key exist in getSigners(). I check its object reference and saw that it is same as NodeA’s. I don’t see NodeB’s key.

        check.using("The signer must be the borrower.", command.getSigners().contains(borrower.getOwningKey()));

Any fix for this? Thanks…


(Joel Dudley) #2

Hi Erhan - thanks for flagging this. Let me investigate.


(Joel Dudley) #3

Hi Erhan,

I’ve put in a fix for this. In the meantime, if you change the constraint to:

check.using("The signer must be the lender.", command.getSigners().contains(lender.getOwningKey()));

Then contract verification will pass.


(Stefano Maffullo) #4

Are you starting this from the node shell?


(Erhan S) #5

Yes from nodeA’s shell.


(Erhan S) #6

Thanks Joel,
However is that the real solution? Because tutorial emphasizes borrower multiple times in the document. Image on that page also designed for borrower signature.


Thanks…


(Erhan S) #7

Another issue is about next step after Hello. On Two Party Flow part code below does not work and throws IllegealArgument exception because it does not accept null.

        final SignedTransaction fullySignedTx = subFlow(new CollectSignaturesFlow(signedTx,null));

I tried to fix it like in Example (https://github.com/corda/cordapp-tutorial/blob/master/java-source/src/main/java/com/example/flow/ExampleFlow.java) and modified the code like this:

package com.template.flow;

import co.paralleluniverse.fibers.Suspendable;
import com.google.common.collect.ImmutableList;
import com.template.contract.IOUContract;
import com.template.state.IOUState;
import net.corda.core.contracts.Command;
import net.corda.core.contracts.ContractState;
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.security.PublicKey;
import java.util.List;

import static net.corda.core.contracts.ContractsDSL.requireThat;
public class IOUFlow {
@InitiatingFlow
@StartableByRPC
public static class Initiator extends FlowLogic {
private final Integer iouValue;
private final Party otherParty;

    // The progress tracker checkpoints each stage of the flow and outputs the specified messages when each
    // checkpoint is reached in the code. See the 'progressTracker.currentStep' expressions within the call()
    // function.
    private final ProgressTracker progressTracker = new ProgressTracker(
            GENERATING_TRANSACTION,
            VERIFYING_TRANSACTION,
            SIGNING_TRANSACTION,
            GATHERING_SIGS,
            FINALISING_TRANSACTION
    );

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

    /**
     * The flow logic is encapsulated within the call() method.
     */
    @Suspendable
    @Override
    public Void call() throws FlowException {
        // We retrieve the required identities from the network map.
        final Party me = getServiceHub().getMyInfo().getLegalIdentity();
        final Party notary = getServiceHub().getNetworkMapCache().getAnyNotary(null);

        progressTracker.setCurrentStep(GENERATING_TRANSACTION);

        // We create a transaction builder
        final TransactionBuilder txBuilder = new TransactionBuilder();
        txBuilder.setNotary(notary);

        // We add the items to the builder.
        IOUState state = new IOUState(iouValue, me, otherParty);
        List<PublicKey> requiredSigners = ImmutableList.of(me.getOwningKey(), otherParty.getOwningKey());
        Command cmd = new Command(new IOUContract.Create(), requiredSigners);
        txBuilder.withItems(state, cmd);

        progressTracker.setCurrentStep(VERIFYING_TRANSACTION);

        // Verifying the transaction.
        txBuilder.verify(getServiceHub());

        // Signing the transaction.
        progressTracker.setCurrentStep(SIGNING_TRANSACTION);

        final SignedTransaction signedTx = getServiceHub().signInitialTransaction(txBuilder);

        progressTracker.setCurrentStep(GATHERING_SIGS);

        final SignedTransaction fullySignedTx = subFlow(new CollectSignaturesFlow(signedTx, progressTracker));

        // Finalising the transaction.
        progressTracker.setCurrentStep(FINALISING_TRANSACTION);

        subFlow(new FinalityFlow(fullySignedTx));


        return null;
    }
}
@InitiatedBy(Initiator.class)
public static class Acceptor extends FlowLogic<Void> {

    private final Party otherParty;

    public Acceptor(Party otherParty) {
        this.otherParty = otherParty;
    }

    @Suspendable
    @Override
    public Void call() throws FlowException {
        class signTxFlow extends SignTransactionFlow {
            private signTxFlow(Party otherParty) {
                super(otherParty, null);
            }

            @Override
            protected void checkTransaction(SignedTransaction stx) {
                requireThat(require -> {
                    ContractState output = stx.getTx().getOutputs().get(0).getData();
                    require.using("This must be an IOU transaction.", output instanceof IOUState);
                    IOUState iou = (IOUState) output;
                    require.using("The IOU's value can't be too high.", iou.getValue() < 100);
                    return null;
                });
            }
        }

        subFlow(new signTxFlow(otherParty));

        return null;
    }
}

}

But then, I am getting StackOverflow (see below), because ProgressTracker code gets into infinite loop at

    final SignedTransaction fullySignedTx = subFlow(new CollectSignaturesFlow(signedTx, progressTracker));

while checking child steps. I debugged and saw that GATHERING_SIGS step has itself assigned as child. Is it a bug or am I doing something wrong?

[WARN ] 2017-08-16T03:51:58,242Z [Node thread] flow.[f59d9b4e-b41b-4eea-9947-b1a52819c2f6].run - Terminated by unexpected exception
java.lang.StackOverflowError: null
at net.corda.core.utilities.ProgressTracker.getChildProgressTracker(ProgressTracker.kt:130) ~[corda-core-0.14.0.jar:?]
at net.corda.core.utilities.ProgressTracker.getCurrentStepRecursive(ProgressTracker.kt:128) ~[corda-core-0.14.0.jar:?]
at net.corda.core.utilities.ProgressTracker.getCurrentStepRecursive(ProgressTracker.kt:128) ~[corda-core-0.14.0.jar:?]
at net.corda.core.utilities.ProgressTracker.getCurrentStepRecursive(ProgressTracker.kt:128) ~[corda-core-0.14.0.jar:?]
at net.corda.core.utilities.ProgressTracker.getCurrentStepRecursive(ProgressTracker.kt:128) ~[corda-core-0.14.0.jar:?]
at net.corda.core.utilities.ProgressTracker.getCurrentStepRecursive(ProgressTracker.kt:128) ~[corda-core-0.14.0.jar:?]
at net.corda.core.utilities.ProgressTracker.getCurrentStepRecursive(ProgressTracker.kt:128) ~[corda-core-0.14.0.jar:?]


(Joel Dudley) #8

Hi Erhan,

Thanks for your feedback. Requiring the borrower’s signature instead of the lender’s is a remnant of a previous version of the tutorial, where both sides signed the transaction.

We’ve created an updated version of the tutorial on the website: https://docs.corda.net/hello-world-index.html.

We will also look into the issue with the null passed to CollectSignaturesFlow.


(Joel Dudley) #9

Hi Erhan,

This issue is now fixed. Please take a look at the updated tutorial here: https://docs.corda.net/hello-world-index.html.


(Erhan S) #10

Thanks for quick fix. It is working now. I have one question about the console. When I submit start flow it does not return to cursor and accept other commands. On nodeA I have to press ctrl+C and on nodeB console I have to hit Enter. When I run valid transactions and vault queries as advised I see trxs and ledger items as seen on the tutorial Is that normal?


(Joel Dudley) #11

Hi Erhan,

The node shell uses the flow’s progress tracker to establish when the flow has completed. Are you sure you have overridden the progressTracker in your flow, including the getter for Java?


(Erhan S) #12

Hi,
I copied and pasted the flow code in the tutorial. I don’t see any override or reference to ProgressTracker other than

CollectSignaturesFlow.Companion.tracker()

Are there other snippet that I should have used?


(Ravikumar kayagurala) #14

I am trying to build the solution it is trying to download lots of files i am in offline environment can anyone help to me to install total files manually.