예제 #1
0
  private Script parseScriptString(String string) throws Exception {
    String[] words = string.split("[ \\t\\n]");

    UnsafeByteArrayOutputStream out = new UnsafeByteArrayOutputStream();

    for (String w : words) {
      if (w.equals("")) continue;
      if (w.matches("^-?[0-9]*$")) {
        // Number
        long val = Long.parseLong(w);
        if (val >= -1 && val <= 16) out.write(Script.encodeToOpN((int) val));
        else
          Script.writeBytes(
              out, Utils.reverseBytes(Utils.encodeMPI(BigInteger.valueOf(val), false)));
      } else if (w.matches("^0x[0-9a-fA-F]*$")) {
        // Raw hex data, inserted NOT pushed onto stack:
        out.write(Hex.decode(w.substring(2)));
      } else if (w.length() >= 2 && w.startsWith("'") && w.endsWith("'")) {
        // Single-quoted string, pushed as data. NOTE: this is poor-man's
        // parsing, spaces/tabs/newlines in single-quoted strings won't work.
        Script.writeBytes(out, w.substring(1, w.length() - 1).getBytes(Charset.forName("UTF-8")));
      } else if (ScriptOpCodes.getOpCode(w) != OP_INVALIDOPCODE) {
        // opcode, e.g. OP_ADD or OP_1:
        out.write(ScriptOpCodes.getOpCode(w));
      } else if (w.startsWith("OP_")
          && ScriptOpCodes.getOpCode(w.substring(3)) != OP_INVALIDOPCODE) {
        // opcode, e.g. OP_ADD or OP_1:
        out.write(ScriptOpCodes.getOpCode(w.substring(3)));
      } else {
        throw new RuntimeException("Invalid Data");
      }
    }

    return new Script(out.toByteArray());
  }
예제 #2
0
 @Test
 public void testIp() throws Exception {
   byte[] bytes =
       Hex.decode(
           "41043e96222332ea7848323c08116dddafbfa917b8e37f0bdf63841628267148588a09a43540942d58d49717ad3fabfe14978cf4f0a8b84d2435dad16e9aa4d7f935ac");
   Script s = new Script(bytes);
   assertTrue(s.isSentToRawPubKey());
 }
예제 #3
0
 @Test
 public void testScriptSig() throws Exception {
   byte[] sigProgBytes = Hex.decode(sigProg);
   Script script = new Script(sigProgBytes);
   // Test we can extract the from address.
   byte[] hash160 = Utils.sha256hash160(script.getPubKey());
   Address a = new Address(params, hash160);
   assertEquals("mkFQohBpy2HDXrCwyMrYL5RtfrmeiuuPY2", a.toString());
 }
예제 #4
0
 @Test
 public void testScriptPubKey() throws Exception {
   // Check we can extract the to address
   byte[] pubkeyBytes = Hex.decode(pubkeyProg);
   Script pubkey = new Script(pubkeyBytes);
   assertEquals(
       "DUP HASH160 [33e81a941e64cda12c6a299ed322ddbdd03f8d0e] EQUALVERIFY CHECKSIG",
       pubkey.toString());
   Address toAddr = new Address(params, pubkey.getPubKeyHash());
   assertEquals("mkFQohBpy2HDXrCwyMrYL5RtfrmeiuuPY2", toAddr.toString());
 }
예제 #5
0
 @Test
 public void testMultiSig() throws Exception {
   List<ECKey> keys = Lists.newArrayList(new ECKey(), new ECKey(), new ECKey());
   assertTrue(ScriptBuilder.createMultiSigOutputScript(2, keys).isSentToMultiSig());
   assertTrue(ScriptBuilder.createMultiSigOutputScript(3, keys).isSentToMultiSig());
   assertFalse(ScriptBuilder.createOutputScript(new ECKey()).isSentToMultiSig());
   try {
     // Fail if we ask for more signatures than keys.
     Script.createMultiSigOutputScript(4, keys);
     fail();
   } catch (Throwable e) {
     // Expected.
   }
   try {
     // Must have at least one signature required.
     Script.createMultiSigOutputScript(0, keys);
   } catch (Throwable e) {
     // Expected.
   }
   // Actual execution is tested by the data driven tests.
 }
예제 #6
0
  @Test
  public void dataDrivenInvalidScripts() throws Exception {
    BufferedReader in =
        new BufferedReader(
            new InputStreamReader(
                getClass().getResourceAsStream("script_invalid.json"), Charset.forName("UTF-8")));

    NetworkParameters params = TestNet3Params.get();

    // Poor man's JSON parser (because pulling in a lib for this is overkill)
    String script = "";
    while (in.ready()) {
      String line = in.readLine();
      if (line == null || line.equals("")) continue;
      script += line;
      if (line.equals("]") && script.equals("]") && !in.ready()) break; // ignore last ]
      if (line.trim().endsWith("],") || line.trim().equals("]")) {
        String[] scripts = script.split(",");
        try {
          scripts[0] = scripts[0].replaceAll("[\"\\[\\]]", "").trim();
          scripts[1] = scripts[1].replaceAll("[\"\\[\\]]", "").trim();
          Script scriptSig = parseScriptString(scripts[0]);
          Script scriptPubKey = parseScriptString(scripts[1]);

          scriptSig.correctlySpends(new Transaction(params), 0, scriptPubKey, true);
          System.err.println("scriptSig: " + scripts[0]);
          System.err.println("scriptPubKey: " + scripts[1]);
          System.err.flush();
          fail();
        } catch (VerificationException e) {
          // Expected.
        }
        script = "";
      }
    }
    in.close();
  }
예제 #7
0
  @Test
  public void testCreateMultiSigInputScript() throws AddressFormatException {
    // Setup transaction and signatures
    ECKey key1 =
        new DumpedPrivateKey(params, "cVLwRLTvz3BxDAWkvS3yzT9pUcTCup7kQnfT2smRjvmmm1wAP6QT")
            .getKey();
    ECKey key2 =
        new DumpedPrivateKey(params, "cTine92s8GLpVqvebi8rYce3FrUYq78ZGQffBYCS1HmDPJdSTxUo")
            .getKey();
    ECKey key3 =
        new DumpedPrivateKey(params, "cVHwXSPRZmL9adctwBwmn4oTZdZMbaCsR5XF6VznqMgcvt1FDDxg")
            .getKey();
    Script multisigScript =
        ScriptBuilder.createMultiSigOutputScript(2, Arrays.asList(key1, key2, key3));
    byte[] bytes =
        Hex.decode(
            "01000000013df681ff83b43b6585fa32dd0e12b0b502e6481e04ee52ff0fdaf55a16a4ef61000000006b483045022100a84acca7906c13c5895a1314c165d33621cdcf8696145080895cbf301119b7cf0220730ff511106aa0e0a8570ff00ee57d7a6f24e30f592a10cae1deffac9e13b990012102b8d567bcd6328fd48a429f9cf4b315b859a58fd28c5088ef3cb1d98125fc4e8dffffffff02364f1c00000000001976a91439a02793b418de8ec748dd75382656453dc99bcb88ac40420f000000000017a9145780b80be32e117f675d6e0ada13ba799bf248e98700000000");
    Transaction transaction = new Transaction(params, bytes);
    TransactionOutput output = transaction.getOutput(1);
    Transaction spendTx = new Transaction(params);
    Address address = new Address(params, "n3CFiCmBXVt5d3HXKQ15EFZyhPz4yj5F3H");
    Script outputScript = ScriptBuilder.createOutputScript(address);
    spendTx.addOutput(output.getValue(), outputScript);
    spendTx.addInput(output);
    Sha256Hash sighash = spendTx.hashForSignature(0, multisigScript, SigHash.ALL, false);
    ECKey.ECDSASignature party1Signature = key1.sign(sighash);
    ECKey.ECDSASignature party2Signature = key2.sign(sighash);
    TransactionSignature party1TransactionSignature =
        new TransactionSignature(party1Signature, SigHash.ALL, false);
    TransactionSignature party2TransactionSignature =
        new TransactionSignature(party2Signature, SigHash.ALL, false);

    // Create p2sh multisig input script
    Script inputScript =
        ScriptBuilder.createP2SHMultiSigInputScript(
            ImmutableList.of(party1TransactionSignature, party2TransactionSignature),
            multisigScript.getProgram());

    // Assert that the input script contains 4 chunks
    assertTrue(inputScript.getChunks().size() == 4);

    // Assert that the input script created contains the original multisig
    // script as the last chunk
    ScriptChunk scriptChunk = inputScript.getChunks().get(inputScript.getChunks().size() - 1);
    Assert.assertArrayEquals(scriptChunk.data, multisigScript.getProgram());

    // Create regular multisig input script
    inputScript =
        ScriptBuilder.createMultiSigInputScript(
            ImmutableList.of(party1TransactionSignature, party2TransactionSignature));

    // Assert that the input script only contains 3 chunks
    assertTrue(inputScript.getChunks().size() == 3);

    // Assert that the input script created does not end with the original
    // multisig script
    scriptChunk = inputScript.getChunks().get(inputScript.getChunks().size() - 1);
    Assert.assertThat(scriptChunk.data, IsNot.not(IsEqual.equalTo(multisigScript.getProgram())));
  }