6

I am implementing Stellar Smart Contract where in account has 2 signers. Goal is second signer can withdraw funds after certain date and if not withdrawn first signer can recover / transfer the funds. I am using Stellar Java SDK to create transaction

SetOptionsOperation unlockOperation = new SetOptionsOperation.Builder()
                .setSigner(party2AccountPair.getXdrSignerKey(), 1)
                .setMasterKeyWeight(0).setLowThreshold(1)
                .setMediumThreshold(1).setHighThreshold(1).build();
ZonedDateTime currentDate = ZonedDateTime.now( ZoneOffset.UTC );
long minTime = currentDate.toEpochSecond() + 300;
long maxTime = minTime + 86400;

TimeBounds timeBounds = new TimeBounds(minTime, maxTime);
Transaction unlockTransaction = new Transaction.Builder(escrowAccount)
  .addOperation(unlockOperation).addTimeBounds(timeBounds).build();
unlockTransaction.sign(escrowAccountPair);

Above code sets the signer option. I need the second signer to sign the transaction.

String unlockTransactiondr = unlockTransaction.toEnvelopeXdrBase64();

Generate the transaction XDR and it will be send to signer 2.

BaseEncoding base64Encoding = BaseEncoding.base64();
byte[] bytes = base64Encoding.decode(unlockTransactiondr);
TransactionEnvelope transactionEnvelope = TransactionEnvelope.decode(
  new XdrDataInputStream(new ByteArrayInputStream(bytes))
);

Signer 2 gets the base64 string and creates a TransactionEnvelope.

Question

  1. How can Signer 2 sign the transaction? What API to use? Signer 2 has the XDR format transaction. TransactionEnvelope has API to get the DecoratedSignature[]; is this the array of signatures. If yes how can I create new DecoratedSignature and add to the array. DecoratedSignature needs org.stellar.sdk.xdr.Signature, how can I create this object using KeyPair of Signer 2
  2. How can I use Java Stellar SDK to post TransactionEnvelope to Horizon server.

Is the below code correct for Signer 2 sign the transaction. If yes it answers question 1 how signer 2 can sign the transaction. Question 2 is still open. I can test the code once I have the way to submit the TransactionEnvelope

ByteArrayOutputStream bOut= new ByteArrayOutputStream();
XdrDataOutputStream x = new XdrDataOutputStream(bOut);
SignerKey.encode(x, party2AccountPair.getXdrSignerKey());
Signature sig = Signature.decode(new XdrDataInputStream(new ByteArrayInputStream(bOut.toByteArray())));

DecoratedSignature party2Sig = new DecoratedSignature();
party2Sig.setHint(party2AccountPair.getSignatureHint());
party2Sig.setSignature(sig);

DecoratedSignature[] dSigs = transactionEnvelope.getSignatures();

DecoratedSignature[] updatedDSigs = new DecoratedSignature[dSigs.length+1];

for(int i=0, iLen=dSigs.length; i<iLen; i++) {
    updatedDSigs[i] = dSigs[i];
}

updatedDSigs[updatedDSigs.length-1] = party2Sig;

transactionEnvelope.setSignatures(updatedDSigs);

If I use the above code and try to decode, it throws exception non-zero padding while decoding the second signature

java.io.IOException: non-zero padding
at org.stellar.sdk.xdr.XdrDataInputStream$XdrInputStream.pad(XdrDataInputStream.java:124)
at org.stellar.sdk.xdr.XdrDataInputStream$XdrInputStream.read(XdrDataInputStream.java:110)
at java.io.DataInputStream.read(DataInputStream.java:149)
at org.stellar.sdk.xdr.Signature.decode(Signature.java:31)
at org.stellar.sdk.xdr.DecoratedSignature.decode(DecoratedSignature.java:41)
at org.stellar.sdk.xdr.TransactionEnvelope.decode(TransactionEnvelope.java:51)
at stellar.SmartContract.main(SmartContract.java:174)

Exception occurs because signature length is 0

Should I be using below code to sign the transaction

party2AccountPair.signDecorated(byte[])

Above code I believe needs transaction hash data in byte[]. How can I get the transaction hash for org.stellar.sdk.xdr.Transaction

Thanks for all the help and support.

  • Any help how to proceed? – Harmit Apr 13 '18 at 16:26
  • I am stuck at similar point in C# SDK. There is no function to submit transaction from XDR to network. – jagstock Jul 9 '18 at 8:43
1

When this question was first asked, the latest version of the Java Stellar SDK was 0.2.0 and it did not support all of the envelope-XDR-conversion and transaction-submitting needed to do what the questioner was trying to do. But the 0.2.2 release this past summer took care of much/all of that and the current release (0.4.1) definitely has the methods. Without getting too much into the weeds of the specific code above, here's a very simple flow that you can now do with the Stellar Java SDK.

Server server = new Server("https://horizon-testnet.stellar.org");
Transaction transaction = Transaction.fromEnvelopeXdr("AAAAAPCBdywb.....GNdhH5FAw==");     
SubmitTransactionResponse response = server.submitTransaction(transaction);

This code makes a connection to the Horizon server, converts an XDR String into a Transaction object, and then submits the Transaction to the Stellar network.

  • Thanks for the response. Will give it a try with newer version of Stellar – Harmit Jan 24 at 22:25

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.