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
- 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
- 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.