package network.thunder.core.etc;
import org.bitcoinj.core.*;
import org.bitcoinj.crypto.TransactionSignature;
import org.bitcoinj.script.Script;
import org.bitcoinj.script.ScriptBuilder;
import org.junit.Before;
import org.junit.Test;
import java.security.NoSuchAlgorithmException;
import java.util.Arrays;
import static junit.framework.TestCase.assertFalse;
import static org.junit.Assert.assertTrue;
/**
* Created by matsjerratsch on 04/11/15.
*/
public class ScriptToolsTest {
ECKey keyServer = ECKey.fromPrivate(Tools.hexStringToByteArray("95b9ba99ce547d0346ae69adeef116b51c77f3285fe8941c9bfe83a0857d606e"));
ECKey keyClient = ECKey.fromPrivate(Tools.hexStringToByteArray("514651734ecf29afc45e520854842ad0aff937418be72b7e5b688b0fc0ef8661"));
ECKey keyServerA = ECKey.fromPrivate(Tools.hexStringToByteArray("ea827f0b72fad12d46ce11da5db814433711fa15bcd834b9a94de5fb3319b71d"));
ECKey keyClientA = ECKey.fromPrivate(Tools.hexStringToByteArray("1ae1c7ca3d0e0d8372d7111a231a0d45bf7abeff22342db7ab3d4d200b7f4ce5"));
Transaction transactionOutput;
Transaction transactionInput;
byte[] secretServer = Tools.hexStringToByteArray("E34BAF76398A2E167EC4CB8BE4A8C75E19255CB0");
byte[] secretClient = Tools.hexStringToByteArray("E650A18B973A949DDF1854E6206620F07F8C49ED");
byte[] secretServerHash = Tools.hashSecret(secretServer);
byte[] secretClientHash = Tools.hashSecret(secretClient);
byte[] revocationServer = Tools.hexStringToByteArray("E3411336485A2E167EC4CB8BE4A8C75E19255CB0");
byte[] revocationClient = Tools.hexStringToByteArray("E65AA748832A949DDF1854E6206620F07F8C49ED");
byte[] revocationServerHash = Tools.hashSecret(revocationServer);
byte[] revocationClientHash = Tools.hashSecret(revocationClient);
NetworkParameters params = NetworkParameters.testNet3();
@Before
public void setup () throws NoSuchAlgorithmException {
Context.getOrCreate(params);
transactionOutput = new Transaction(params);
transactionInput = new Transaction(params);
}
@Test
public void shouldCreateSpendableAnchorTransactionWithEscapeTransaction () {
Script outputScript = ScriptTools.getAnchorOutputScript(secretServerHash, keyClient, keyClientA, keyServer);
Script outputScriptP2SH = ScriptBuilder.createP2SHOutputScript(outputScript);
transactionInput.addInput(Sha256Hash.wrap("6d651fd23456606298348f7e750321cba2e3e752d433aa537ea289593645d2e4"), 0, Tools.getDummyScript());
transactionInput.addOutput(Coin.valueOf(999000), Tools.getDummyScript());
TransactionSignature signatureClientA = Tools.getSignature(transactionInput, 0, outputScript.getProgram(), keyClientA);
TransactionSignature signatureServer = Tools.getSignature(transactionInput, 0, outputScript.getProgram(), keyServer);
Script inputScript = ScriptTools.getEscapeInputScript(signatureClientA.encodeToBitcoin(), signatureServer.encodeToBitcoin(), secretServer,
secretServerHash, keyClient, keyClientA, keyServer);
transactionInput.getInput(0).setScriptSig(inputScript);
inputScript.correctlySpends(transactionInput, 0, outputScriptP2SH);
}
@Test
public void shouldCreateSpendableAnchorTransactionWithCommitmentTransaction () {
Script outputScript = ScriptTools.getAnchorOutputScript(secretServerHash, keyClient, keyClientA, keyServer);
Script outputScriptP2SH = ScriptBuilder.createP2SHOutputScript(outputScript);
transactionInput.addInput(Sha256Hash.wrap("6d651fd23456606298348f7e750321cba2e3e752d433aa537ea289593645d2e4"), 0, Tools.getDummyScript());
transactionInput.addOutput(Coin.valueOf(999000), Tools.getDummyScript());
TransactionSignature signatureClient = Tools.getSignature(transactionInput, 0, outputScript.getProgram(), keyClient);
TransactionSignature signatureServer = Tools.getSignature(transactionInput, 0, outputScript.getProgram(), keyServer);
Script inputScript = ScriptTools.getCommitInputScript(signatureClient.encodeToBitcoin(), signatureServer.encodeToBitcoin(),
secretServerHash, keyClient, keyClientA, keyServer);
transactionInput.getInput(0).setScriptSig(inputScript);
inputScript.correctlySpends(transactionInput, 0, outputScriptP2SH);
}
@Test
public void shouldCreateSpendableEscapeTransactionWithRevocationTransaction () {
Script outputScript = ScriptTools.getEscapeOutputScript(revocationServerHash, keyServer, keyClient, 60 * 60 * 1000);
Script outputScriptP2SH = ScriptBuilder.createP2SHOutputScript(outputScript);
transactionInput.addInput(Sha256Hash.wrap("6d651fd23456606298348f7e750321cba2e3e752d433aa537ea289593645d2e4"), 0, Tools.getDummyScript());
transactionInput.addOutput(Coin.valueOf(999000), Tools.getDummyScript());
TransactionSignature signatureClient = Tools.getSignature(transactionInput, 0, outputScript.getProgram(), keyClient);
Script inputScript = ScriptTools.getEscapeInputRevocationScript(revocationServerHash, keyServer, keyClient, 60 * 60 * 1000, signatureClient
.encodeToBitcoin(), revocationServer);
transactionInput.getInput(0).setScriptSig(inputScript);
inputScript.correctlySpends(transactionInput, 0, outputScriptP2SH);
}
@Test
public void shouldCreateSpendableEscapeTransactionWithTimeoutTransaction () {
Script outputScript = ScriptTools.getEscapeOutputScript(revocationServerHash, keyServer, keyClient, 60 * 60 * 1000);
Script outputScriptP2SH = ScriptBuilder.createP2SHOutputScript(outputScript);
transactionInput.addInput(Sha256Hash.wrap("6d651fd23456606298348f7e750321cba2e3e752d433aa537ea289593645d2e4"), 0, Tools.getDummyScript());
transactionInput.addOutput(Coin.valueOf(999000), Tools.getDummyScript());
TransactionSignature signatureServer = Tools.getSignature(transactionInput, 0, outputScript.getProgram(), keyServer);
Script inputScript = ScriptTools.getEscapeInputTimeoutScript(revocationServerHash, keyServer, keyClient, 60 * 60 * 1000, signatureServer
.encodeToBitcoin());
transactionInput.getInput(0).setScriptSig(inputScript);
inputScript.correctlySpends(transactionInput, 0, outputScriptP2SH);
}
@Test
public void shouldCreateSpendableFastEscapeTransactionWithSecretTransaction () {
Script outputScript = ScriptTools.getFastEscapeOutputScript(secretClientHash, keyServer, keyClient, 60 * 60 * 1000);
Script outputScriptP2SH = ScriptBuilder.createP2SHOutputScript(outputScript);
transactionInput.addInput(Sha256Hash.wrap("6d651fd23456606298348f7e750321cba2e3e752d433aa537ea289593645d2e4"), 0, Tools.getDummyScript());
transactionInput.addOutput(Coin.valueOf(999000), Tools.getDummyScript());
TransactionSignature signatureServer = Tools.getSignature(transactionInput, 0, outputScript.getProgram(), keyServer);
Script inputScript = ScriptTools.getFastEscapeInputSecretScript(secretClientHash, keyServer, keyClient, 60 * 60 * 1000, signatureServer
.encodeToBitcoin(), secretClient);
transactionInput.getInput(0).setScriptSig(inputScript);
inputScript.correctlySpends(transactionInput, 0, outputScriptP2SH);
}
@Test
public void shouldCreateSpendableFastEscapeTransactionWithTimeoutTransaction () {
Script outputScript = ScriptTools.getFastEscapeOutputScript(secretClientHash, keyServer, keyClient, 60 * 60 * 1000);
Script outputScriptP2SH = ScriptBuilder.createP2SHOutputScript(outputScript);
transactionInput.addInput(Sha256Hash.wrap("6d651fd23456606298348f7e750321cba2e3e752d433aa537ea289593645d2e4"), 0, Tools.getDummyScript());
transactionInput.addOutput(Coin.valueOf(999000), Tools.getDummyScript());
TransactionSignature signatureClient = Tools.getSignature(transactionInput, 0, outputScript.getProgram(), keyClient);
Script inputScript = ScriptTools.getFastEscapeInputTimeoutScript(secretClientHash, keyServer, keyClient, 60 * 60 * 1000, signatureClient
.encodeToBitcoin());
transactionInput.getInput(0).setScriptSig(inputScript);
inputScript.correctlySpends(transactionInput, 0, outputScriptP2SH);
}
@Test(expected = ScriptException.class)
public void shouldThrowExceptionBecauseOfWrongSecretWhenTryingToSpendEscapeTransaction () {
Script outputScript = ScriptTools.getEscapeOutputScript(secretServerHash, keyServer, keyClient, 60 * 60 * 1000);
Script outputScriptP2SH = ScriptBuilder.createP2SHOutputScript(outputScript);
transactionInput.addInput(Sha256Hash.wrap("6d651fd23456606298348f7e750321cba2e3e752d433aa537ea289593645d2e4"), 0, Tools.getDummyScript());
transactionInput.addOutput(Coin.valueOf(999000), Tools.getDummyScript());
TransactionSignature signatureClient = Tools.getSignature(transactionInput, 0, outputScript.getProgram(), keyClient);
byte[] b = new byte[]{0x00};
System.arraycopy(b, 0, secretServer, 15, 1); //Copy a wrong byte into the secret, should not work anymore now
Script inputScript = ScriptTools.getEscapeInputRevocationScript(secretServerHash, keyServer, keyClient, 60 * 60 * 1000, signatureClient
.encodeToBitcoin(), secretServer);
transactionInput.getInput(0).setScriptSig(inputScript);
inputScript.correctlySpends(transactionInput, 0, outputScriptP2SH);
}
@Test(expected = ScriptException.class)
public void shouldThrowExceptionBecauseOfWrongSecretWhenTryingToSpendFastEscapeTransaction () {
Script outputScript = ScriptTools.getFastEscapeOutputScript(secretClientHash, keyServer, keyClient, 60 * 60 * 1000);
Script outputScriptP2SH = ScriptBuilder.createP2SHOutputScript(outputScript);
transactionInput.addInput(Sha256Hash.wrap("6d651fd23456606298348f7e750321cba2e3e752d433aa537ea289593645d2e4"), 0, Tools.getDummyScript());
transactionInput.addOutput(Coin.valueOf(999000), Tools.getDummyScript());
TransactionSignature signatureServer = Tools.getSignature(transactionInput, 0, outputScript.getProgram(), keyServer);
byte[] b = new byte[]{0x00};
System.arraycopy(b, 0, secretClient, 15, 1); //Copy a wrong byte into the secret, should not work anymore now
Script inputScript = ScriptTools.getFastEscapeInputSecretScript(secretClientHash, keyServer, keyClient, 60 * 60 * 1000, signatureServer
.encodeToBitcoin(), secretClient);
transactionInput.getInput(0).setScriptSig(inputScript);
inputScript.correctlySpends(transactionInput, 0, outputScriptP2SH);
}
@Test(expected = ScriptException.class)
public void shouldThrowExceptionBecauseSignatureOrderIsNotCorrect () {
Script outputScript = ScriptTools.getAnchorOutputScript(secretServerHash, keyClient, keyClientA, keyServer);
Script outputScriptP2SH = ScriptBuilder.createP2SHOutputScript(outputScript);
transactionInput.addInput(Sha256Hash.wrap("6d651fd23456606298348f7e750321cba2e3e752d433aa537ea289593645d2e4"), 0, Tools.getDummyScript());
transactionInput.addOutput(Coin.valueOf(999000), Tools.getDummyScript());
TransactionSignature signatureClientA = Tools.getSignature(transactionInput, 0, outputScript.getProgram(), keyClientA);
TransactionSignature signatureServer = Tools.getSignature(transactionInput, 0, outputScript.getProgram(), keyServer);
Script inputScript = ScriptTools.getEscapeInputScript(signatureServer.encodeToBitcoin(), signatureClientA.encodeToBitcoin(), secretServer,
secretServerHash, keyClient, keyClientA, keyServer);
transactionInput.getInput(0).setScriptSig(inputScript);
inputScript.correctlySpends(transactionInput, 0, outputScriptP2SH);
}
@Test
public void shouldProduceCorrectScript () throws Exception {
byte[] p1 = Tools.hexStringToByteArray("aa bb cc dd ee");
byte[] p2 = Tools.hexStringToByteArray("04 92 84 00 82 71 00 74 38 92 48 17");
byte[] p3 = Tools.hexStringToByteArray("08 79 66 88");
byte[] p4 = Tools.hexStringToByteArray("09 87 09 38 27 aa 98 00 83 a9 ff 89 11 39 47 89 28 11 99 02 83 99 04 28 40 66 78 09 65");
Script script = ScriptTools.produceScript(ScriptTools.ANCHOR_OUTPUT_SCRIPT, p1, p2, p3, p4);
assertTrue(Arrays.equals(script.getProgram(), Tools.hexStringToByteArray
("A905AABBCCDDEE87630C04928400827100743892481767040879668868527C1D0987093827AA980083A9FF89113947892811990283990428406678096552AE")));
}
@Test
public void testScriptShouldReturnTrue () throws Exception {
byte[] script = Tools.hexStringToByteArray
("A905AABBCCDDEE87630C04928400827100743892481767040879668868527C1D0987093827AA980083A9FF89113947892811990283990428406678096552AE");
byte[] p1 = Tools.hexStringToByteArray("aa bb cc dd ee");
byte[] p2 = Tools.hexStringToByteArray("04 92 84 00 82 71 00 74 38 92 48 17");
byte[] p3 = Tools.hexStringToByteArray("08 79 66 88");
byte[] p4 = Tools.hexStringToByteArray("09 87 09 38 27 aa 98 00 83 a9 ff 89 11 39 47 89 28 11 99 02 83 99 04 28 40 66 78 09 65");
assertTrue(ScriptTools.testScript(script, ScriptTools.ANCHOR_OUTPUT_SCRIPT, p1, p2, p3, p4));
}
@Test
public void testScriptShouldReturnFalse () throws Exception {
//Changed one byte of the original sequence
byte[] script = Tools.hexStringToByteArray
("A905AABBCCDDEE87630C049284008271007438924817570408796688527C1D0987093827AA980083A9FF89113947892811990283990428406678096552AE");
byte[] p1 = Tools.hexStringToByteArray("aa bb cc dd ee");
byte[] p2 = Tools.hexStringToByteArray("04 92 84 00 82 71 00 74 38 92 48 17");
byte[] p3 = Tools.hexStringToByteArray("08 79 66 88");
byte[] p4 = Tools.hexStringToByteArray("09 87 09 38 27 aa 98 00 83 a9 ff 89 11 39 47 89 28 11 99 02 83 99 04 28 40 66 78 09 65");
assertFalse(ScriptTools.testScript(script, ScriptTools.ANCHOR_OUTPUT_SCRIPT, p1, p2, p3, p4));
}
}