mirror of
https://github.com/Qortal/altcoinj.git
synced 2025-01-31 07:12:17 +00:00
Delete some dead code in Script that was confusing people; BitCoinJ does not run scripts.
Remove build.xml as we've switched to Maven.
This commit is contained in:
parent
78bdd09189
commit
3498763d18
51
build.xml
51
build.xml
@ -1,51 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<project name="bitcoinj" default="all">
|
|
||||||
<target name="init">
|
|
||||||
<tstamp/>
|
|
||||||
<mkdir dir="out"/>
|
|
||||||
<mkdir dir="docs"/>
|
|
||||||
</target>
|
|
||||||
|
|
||||||
<target name="compile" depends="init">
|
|
||||||
<javac destdir="out" includeantruntime="no">
|
|
||||||
<src path="src"/>
|
|
||||||
<src path="tests"/>
|
|
||||||
<classpath path="lib/junit-4.8.2.jar"/>
|
|
||||||
<classpath path="lib/slf4j-api-1.6.1.jar"/>
|
|
||||||
<classpath path="lib/slf4j-simple-1.6.1.jar"/>
|
|
||||||
</javac>
|
|
||||||
</target>
|
|
||||||
|
|
||||||
<target name="docs" depends="init">
|
|
||||||
<javadoc sourcepath="src"
|
|
||||||
excludepackagenames="com.google.bitcoin.bouncycastle.*,com.google.bitcoin.examples.*"
|
|
||||||
destdir="docs"
|
|
||||||
additionalparam="-notimestamp"
|
|
||||||
classpath="lib/slf4j-api-1.6.1.jar"/>
|
|
||||||
</target>
|
|
||||||
|
|
||||||
<target name="test" depends="compile">
|
|
||||||
<junit showoutput="false">
|
|
||||||
<classpath path="lib/junit-4.8.2.jar:out"/>
|
|
||||||
<classpath path="lib/slf4j-api-1.6.1.jar:out"/>
|
|
||||||
<classpath path="lib/slf4j-simple-1.6.1.jar:out"/>
|
|
||||||
<batchtest>
|
|
||||||
<fileset dir="tests"><include name="**/*.java"/></fileset>
|
|
||||||
<formatter type="brief" usefile="no"/>
|
|
||||||
</batchtest>
|
|
||||||
</junit>
|
|
||||||
</target>
|
|
||||||
|
|
||||||
<target name="dist" depends="compile">
|
|
||||||
<mkdir dir="dist"/>
|
|
||||||
<jar jarfile="dist/bitcoinj-${DSTAMP}.jar" basedir="out"/>
|
|
||||||
</target>
|
|
||||||
|
|
||||||
<target name="all" depends="dist,docs,test"/>
|
|
||||||
|
|
||||||
<target name="clean">
|
|
||||||
<delete dir="out"/>
|
|
||||||
<delete dir="dist"/>
|
|
||||||
<delete dir="docs"/>
|
|
||||||
</target>
|
|
||||||
</project>
|
|
@ -54,23 +54,11 @@ public class Script {
|
|||||||
byte[] program;
|
byte[] program;
|
||||||
private int cursor;
|
private int cursor;
|
||||||
|
|
||||||
// The stack consists of an ordered series of data buffers growing from zero up.
|
|
||||||
private final Stack<byte[]> stack;
|
|
||||||
// The program is a set of byte[]s where each element is either [opcode] or [data, data, data ...]
|
// The program is a set of byte[]s where each element is either [opcode] or [data, data, data ...]
|
||||||
private List<byte[]> chunks;
|
private List<byte[]> chunks;
|
||||||
private boolean tracing;
|
|
||||||
byte[] programCopy; // TODO: remove this
|
byte[] programCopy; // TODO: remove this
|
||||||
private final NetworkParameters params;
|
private final NetworkParameters params;
|
||||||
|
|
||||||
/** Concatenates two scripts to form a new one. This is used when verifying transactions. */
|
|
||||||
public static Script join(Script a, Script b) throws ScriptException {
|
|
||||||
assert a.params == b.params;
|
|
||||||
byte[] fullProg = new byte[a.programCopy.length + b.programCopy.length];
|
|
||||||
System.arraycopy(a.programCopy, 0, fullProg, 0, a.programCopy.length);
|
|
||||||
System.arraycopy(b.programCopy, 0, fullProg, a.programCopy.length, b.programCopy.length);
|
|
||||||
return new Script(a.params, fullProg, 0, fullProg.length);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Construct a Script using the given network parameters and a range of the programBytes array.
|
* Construct a Script using the given network parameters and a range of the programBytes array.
|
||||||
* @param params Network parameters.
|
* @param params Network parameters.
|
||||||
@ -81,15 +69,9 @@ public class Script {
|
|||||||
*/
|
*/
|
||||||
public Script(NetworkParameters params, byte[] programBytes, int offset, int length) throws ScriptException {
|
public Script(NetworkParameters params, byte[] programBytes, int offset, int length) throws ScriptException {
|
||||||
this.params = params;
|
this.params = params;
|
||||||
stack = new Stack<byte[]>();
|
|
||||||
parse(programBytes, offset, length);
|
parse(programBytes, offset, length);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** If true, running a program will log its instructions. */
|
|
||||||
public void setTracing(boolean value) {
|
|
||||||
this.tracing = value;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Returns the program opcodes as a string, for example "[1234] DUP HAHS160" */
|
/** Returns the program opcodes as a string, for example "[1234] DUP HAHS160" */
|
||||||
public String toString() {
|
public String toString() {
|
||||||
StringBuffer buf = new StringBuffer();
|
StringBuffer buf = new StringBuffer();
|
||||||
@ -240,7 +222,6 @@ public class Script {
|
|||||||
return new Address(params, Utils.sha256hash160(getPubKey()));
|
return new Address(params, Utils.sha256hash160(getPubKey()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the destination address from this script, if it's in the required form (see getPubKey).
|
* Gets the destination address from this script, if it's in the required form (see getPubKey).
|
||||||
* @throws ScriptException
|
* @throws ScriptException
|
||||||
@ -248,110 +229,6 @@ public class Script {
|
|||||||
public Address getToAddress() throws ScriptException {
|
public Address getToAddress() throws ScriptException {
|
||||||
return new Address(params, getPubKeyHash());
|
return new Address(params, getPubKeyHash());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Runs the script with the given Transaction as the "context". Some operations like CHECKSIG
|
|
||||||
* require a transaction to operate on (eg to hash). The context transaction is typically
|
|
||||||
* the transaction having its inputs verified, ie the one where the scriptSig comes from.
|
|
||||||
*/
|
|
||||||
public boolean run(Transaction context) throws ScriptException {
|
|
||||||
for (byte[] chunk : chunks) {
|
|
||||||
if (chunk.length == 1) {
|
|
||||||
int opcode = 0xFF & chunk[0];
|
|
||||||
switch (opcode) {
|
|
||||||
case OP_DUP: opDup(); break;
|
|
||||||
case OP_HASH160: opHash160(); break;
|
|
||||||
case OP_EQUALVERIFY: opEqualVerify(); break;
|
|
||||||
case OP_CHECKSIG: opCheckSig(context); break;
|
|
||||||
default:
|
|
||||||
log.debug("Unknown/unimplemented opcode: {}", opcode);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// Data block, push it onto the stack.
|
|
||||||
log.debug("Push {}", Utils.bytesToHexString(chunk));
|
|
||||||
stack.add(chunk);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
byte[] result = stack.pop();
|
|
||||||
if (result.length != 1)
|
|
||||||
throw new ScriptException("Script left junk at the top of the stack: " + Utils.bytesToHexString(result));
|
|
||||||
return result[0] == 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
void logStack() {
|
|
||||||
for (int i = 0; i < stack.size(); i++) {
|
|
||||||
log.debug("Stack[{}]: {}",i , Utils.bytesToHexString(stack.get(i)));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// WARNING: Unfinished and untested!
|
|
||||||
@SuppressWarnings("unused")
|
|
||||||
private void opCheckSig( Transaction context) throws ScriptException {
|
|
||||||
byte[] pubkey = stack.pop();
|
|
||||||
byte[] sigAndHashType = stack.pop();
|
|
||||||
// The signature has an extra byte on the end to indicate the type of hash. The signature
|
|
||||||
// is over the contents of the program, minus the signature itself of course.
|
|
||||||
byte hashType = sigAndHashType[sigAndHashType.length - 1];
|
|
||||||
// The high bit of the hashType byte is set to indicate "anyone can pay".
|
|
||||||
boolean anyoneCanPay = hashType < 0;
|
|
||||||
// Mask out the top bit.
|
|
||||||
hashType &= (byte)-1 >>> 1;
|
|
||||||
Transaction.SigHash sigHash;
|
|
||||||
switch (hashType) {
|
|
||||||
case 1: sigHash = SigHash.ALL; break;
|
|
||||||
case 2: sigHash = SigHash.NONE; break;
|
|
||||||
case 3: sigHash = SigHash.SINGLE; break;
|
|
||||||
default:
|
|
||||||
// TODO: This should probably not be an exception.
|
|
||||||
throw new ScriptException("Unknown sighash byte: " + sigAndHashType[sigAndHashType.length - 1]);
|
|
||||||
}
|
|
||||||
|
|
||||||
byte[] sig = new byte[sigAndHashType.length - 1];
|
|
||||||
System.arraycopy(sigAndHashType, 0, sig, 0, sig.length);
|
|
||||||
|
|
||||||
log.debug("CHECKSIG: hashtype={} anyoneCanPay={}", sigHash, anyoneCanPay);
|
|
||||||
if (context == null) {
|
|
||||||
// TODO: Fix the unit tests to run scripts in transaction context then remove this.
|
|
||||||
pushBool(true);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
// TODO: Implement me!
|
|
||||||
// Transaction tx = context.simplify(sigHash, 0, anyoneCanPay);
|
|
||||||
|
|
||||||
// The steps to do so are as follows:
|
|
||||||
// - Use the hashtype to fiddle the transaction as appropriate
|
|
||||||
// - Serialize the transaction and hash it
|
|
||||||
// - Use EC code to verify the hash matches the signature
|
|
||||||
pushBool(true);
|
|
||||||
}
|
|
||||||
|
|
||||||
@SuppressWarnings({"SameParameterValue"})
|
|
||||||
private void pushBool(boolean val) {
|
|
||||||
stack.push(new byte[] { val ? (byte)1 : (byte)0 });
|
|
||||||
}
|
|
||||||
|
|
||||||
private void opEqualVerify() throws ScriptException {
|
|
||||||
log.debug("EQUALVERIFY");
|
|
||||||
byte[] a = stack.pop();
|
|
||||||
byte[] b = stack.pop();
|
|
||||||
if (!Arrays.areEqual(a, b))
|
|
||||||
throw new ScriptException("EQUALVERIFY failed: " + Utils.bytesToHexString(a) + " vs " +
|
|
||||||
Utils.bytesToHexString(b));
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Replaces the top item in the stack with a hash160 of it */
|
|
||||||
private void opHash160() {
|
|
||||||
byte[] buf = stack.pop();
|
|
||||||
byte[] hash = Utils.sha256hash160(buf);
|
|
||||||
stack.add(hash);
|
|
||||||
log.debug("HASH160: output is {}", Utils.bytesToHexString(hash));
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Duplicates the top item on the stack */
|
|
||||||
private void opDup() {
|
|
||||||
log.debug("DUP");
|
|
||||||
stack.add(Arrays.clone(stack.lastElement()));
|
|
||||||
}
|
|
||||||
|
|
||||||
////////////////////// Interface for writing scripts from scratch ////////////////////////////////
|
////////////////////// Interface for writing scripts from scratch ////////////////////////////////
|
||||||
|
|
||||||
|
@ -37,7 +37,6 @@ public class ScriptTest {
|
|||||||
public void testScriptSig() throws Exception {
|
public void testScriptSig() throws Exception {
|
||||||
byte[] sigProgBytes = Hex.decode(sigProg);
|
byte[] sigProgBytes = Hex.decode(sigProg);
|
||||||
Script script = new Script(params, sigProgBytes, 0, sigProgBytes.length);
|
Script script = new Script(params, sigProgBytes, 0, sigProgBytes.length);
|
||||||
script.setTracing(true);
|
|
||||||
// Test we can extract the from address.
|
// Test we can extract the from address.
|
||||||
byte[] hash160 = Utils.sha256hash160(script.getPubKey());
|
byte[] hash160 = Utils.sha256hash160(script.getPubKey());
|
||||||
Address a = new Address(params, hash160);
|
Address a = new Address(params, hash160);
|
||||||
@ -51,22 +50,12 @@ public class ScriptTest {
|
|||||||
Script pubkey = new Script(params, pubkeyBytes, 0, pubkeyBytes.length);
|
Script pubkey = new Script(params, pubkeyBytes, 0, pubkeyBytes.length);
|
||||||
Address toAddr = new Address(params, pubkey.getPubKeyHash());
|
Address toAddr = new Address(params, pubkey.getPubKeyHash());
|
||||||
assertEquals("mkFQohBpy2HDXrCwyMrYL5RtfrmeiuuPY2", toAddr.toString());
|
assertEquals("mkFQohBpy2HDXrCwyMrYL5RtfrmeiuuPY2", toAddr.toString());
|
||||||
|
|
||||||
// To verify a transaction as legitimate, both scripts are concatenated and then the whole
|
|
||||||
// thing is run. So check we can do that.
|
|
||||||
byte[] sigBytes = Hex.decode(sigProg);
|
|
||||||
Script sig = new Script(params, sigBytes, 0, sigBytes.length);
|
|
||||||
Script allScript = Script.join(sig, pubkey);
|
|
||||||
allScript.setTracing(true);
|
|
||||||
assertTrue(allScript.run(null));
|
|
||||||
allScript.logStack();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testIp() throws Exception {
|
public void testIp() throws Exception {
|
||||||
byte[] bytes = Hex.decode("41043e96222332ea7848323c08116dddafbfa917b8e37f0bdf63841628267148588a09a43540942d58d49717ad3fabfe14978cf4f0a8b84d2435dad16e9aa4d7f935ac");
|
byte[] bytes = Hex.decode("41043e96222332ea7848323c08116dddafbfa917b8e37f0bdf63841628267148588a09a43540942d58d49717ad3fabfe14978cf4f0a8b84d2435dad16e9aa4d7f935ac");
|
||||||
Script s = new Script(params, bytes, 0, bytes.length);
|
Script s = new Script(params, bytes, 0, bytes.length);
|
||||||
s.setTracing(true);
|
|
||||||
assertTrue(s.isSentToIP());
|
assertTrue(s.isSentToIP());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user