From e141ff0049e745b4272b97ba15c3707437e7a0a8 Mon Sep 17 00:00:00 2001 From: Harald Hoyer Date: Mon, 5 Sep 2016 21:32:32 +0200 Subject: [PATCH] use HMACSHA512256 --- opret-testapp/pom.xml | 2 +- .../java/org/tcpid/opretj/testapp/App.java | 13 +- opretj/pom.xml | 13 +- .../java/org/tcpid/key/HMACSHA512256.java | 18 ++ .../java/org/tcpid/key/MasterSigningKey.java | 48 ++-- .../java/org/tcpid/key/MasterVerifyKey.java | 8 +- .../main/java/org/tcpid/key/VerifyKey.java | 16 +- .../java/org/tcpid/opretj/OPRETECParser.java | 247 ++++++++++-------- .../tcpid/opretj/OPRETHandlerInterface.java | 4 +- .../org/tcpid/opretj/OPRETTransaction.java | 2 +- pom.xml | 2 +- 11 files changed, 205 insertions(+), 168 deletions(-) create mode 100644 opretj/src/main/java/org/tcpid/key/HMACSHA512256.java diff --git a/opret-testapp/pom.xml b/opret-testapp/pom.xml index 1a61de9..82054f2 100644 --- a/opret-testapp/pom.xml +++ b/opret-testapp/pom.xml @@ -48,7 +48,7 @@ org.tcpid opretj - 0.0.1-SNAPSHOT + 0.0.2-SNAPSHOT net.sf.jopt-simple diff --git a/opret-testapp/src/main/java/org/tcpid/opretj/testapp/App.java b/opret-testapp/src/main/java/org/tcpid/opretj/testapp/App.java index 77ce198..0493dbe 100644 --- a/opret-testapp/src/main/java/org/tcpid/opretj/testapp/App.java +++ b/opret-testapp/src/main/java/org/tcpid/opretj/testapp/App.java @@ -46,7 +46,7 @@ public class App { out.flush(); } - private static void displayHelp(PrintWriter out) { + private static void displayHelp(final PrintWriter out) { out.write("Available Commands:\n"); out.write("\n"); out.write("help - this screen\n"); @@ -157,15 +157,6 @@ public class App { } public static void main(final String[] args) throws Exception { - MasterSigningKey sk = SK.getSubKey(1L); - - System.err.println(SK.toString()); - System.err.println(sk.toString()); - sk = SK.getSubKey(2L); - System.err.println(sk.toString()); - sk = SK.getSubKey(3L); - System.err.println(sk.toString()); - System.exit(0); final OptionParser parser = new OptionParser(); final OptionSpec net = parser.accepts("net", "The network to run the examples on") .withRequiredArg().ofType(NetworkEnum.class).defaultsTo(NetworkEnum.TEST); @@ -284,7 +275,7 @@ public class App { kit.awaitTerminated(); } - private static boolean sendOPReturn(final OPRETWalletAppKit kit, PrintWriter output) { + private static boolean sendOPReturn(final OPRETWalletAppKit kit, final PrintWriter output) { final OPRETWallet wallet = kit.opretwallet(); final NetworkParameters params = wallet.getNetworkParameters(); diff --git a/opretj/pom.xml b/opretj/pom.xml index ad74963..8edcaac 100644 --- a/opretj/pom.xml +++ b/opretj/pom.xml @@ -4,10 +4,19 @@ org.tcpid opret-parent - 0.0.1-SNAPSHOT + 0.0.2-SNAPSHOT opretj - + + + oss-sonatype + oss-sonatype + https://oss.sonatype.org/content/repositories/snapshots/ + + true + + + diff --git a/opretj/src/main/java/org/tcpid/key/HMACSHA512256.java b/opretj/src/main/java/org/tcpid/key/HMACSHA512256.java new file mode 100644 index 0000000..dd35539 --- /dev/null +++ b/opretj/src/main/java/org/tcpid/key/HMACSHA512256.java @@ -0,0 +1,18 @@ +package org.tcpid.key; + +import static org.libsodium.jni.NaCl.sodium; + +import org.libsodium.jni.Sodium; +import org.libsodium.jni.crypto.Util; + +public class HMACSHA512256 { + public static final int HMACSHA512256_BYTES = sodium().crypto_auth_hmacsha512256_bytes(); + public static final int HMACSHA512256_KEYBYTES = sodium().crypto_auth_hmacsha512256_keybytes(); + + public static byte[] of(final byte[] key, final byte[] msg) { + final byte[] hash = Util.zeros(HMACSHA512256_BYTES); + final byte[] hashkey = Util.prependZeros(HMACSHA512256_KEYBYTES, key); + Sodium.crypto_auth_hmacsha512256(hash, msg, msg.length, hashkey); + return hash; + } +} diff --git a/opretj/src/main/java/org/tcpid/key/MasterSigningKey.java b/opretj/src/main/java/org/tcpid/key/MasterSigningKey.java index db9a3d8..d28f3ab 100644 --- a/opretj/src/main/java/org/tcpid/key/MasterSigningKey.java +++ b/opretj/src/main/java/org/tcpid/key/MasterSigningKey.java @@ -1,30 +1,22 @@ package org.tcpid.key; import static org.libsodium.jni.NaCl.sodium; -import static org.libsodium.jni.SodiumConstants.SECRETKEY_BYTES; import java.util.ArrayList; -import org.libsodium.jni.Sodium; import org.libsodium.jni.crypto.Hash; -import org.libsodium.jni.crypto.Util; import org.libsodium.jni.encoders.Encoder; import com.google.common.primitives.Longs; public class MasterSigningKey extends SigningKey { + private static final int HMACSHA512256_BYTES = sodium().crypto_auth_hmacsha512256_bytes(); + private static final int HMACSHA512256_KEYBYTES = sodium().crypto_auth_hmacsha512256_keybytes(); + public static final Hash HASH = new Hash(); private MasterSigningKey subkey; private Long subkeyindex; - public static final Hash HASH = new Hash(); private final ArrayList keyindex; - public MasterSigningKey(final byte[] key, ArrayList keyindex) { - super(key); - subkey = null; - subkeyindex = 0L; - this.keyindex = new ArrayList<>(keyindex); - } - public MasterSigningKey(final byte[] key) { super(key); subkey = null; @@ -32,30 +24,30 @@ public class MasterSigningKey extends SigningKey { this.keyindex = new ArrayList<>(); } - public MasterSigningKey getValidSubKey() { - if (subkey == null) { - subkey = getSubKey(subkeyindex); - } - return subkey; + public MasterSigningKey(final byte[] key, final ArrayList keyindex) { + super(key); + subkey = null; + subkeyindex = 0L; + this.keyindex = new ArrayList<>(keyindex); } - public MasterSigningKey getSubKey(Long offset) { - System.err.println("getSubKey"); - final byte[] la = Longs.toByteArray(offset); - final byte[] keynum = Util.prependZeros(16 - la.length, la); - System.err.println("getSubKey key=" + Encoder.HEX.encode(keynum)); - final byte[] appid = Util.prependZeros(14, "EC".getBytes()); - final byte[] newseed = Util.zeros(SECRETKEY_BYTES); - sodium(); - Sodium.crypto_generichash_blake2b_salt_personal(newseed, newseed.length, null, 0, this.seed, this.seed.length, - keynum, appid); + public MasterSigningKey getNextValidSubKey(final Long offset) { + return getSubKey(subkeyindex + offset); + } + + public MasterSigningKey getSubKey(final Long offset) { + final byte[] ob = Longs.toByteArray(offset); + final byte[] newseed = HMACSHA512256.of(seed, ob); final ArrayList ki = new ArrayList<>(this.keyindex); ki.add(offset); return new MasterSigningKey(newseed, ki); } - public MasterSigningKey getNextValidSubKey(Long offset) { - return getSubKey(subkeyindex + offset); + public MasterSigningKey getValidSubKey() { + if (subkey == null) { + subkey = getSubKey(subkeyindex); + } + return subkey; } public void revokeSubKey() { diff --git a/opretj/src/main/java/org/tcpid/key/MasterVerifyKey.java b/opretj/src/main/java/org/tcpid/key/MasterVerifyKey.java index 0b57ff6..c96d43d 100644 --- a/opretj/src/main/java/org/tcpid/key/MasterVerifyKey.java +++ b/opretj/src/main/java/org/tcpid/key/MasterVerifyKey.java @@ -10,6 +10,10 @@ public class MasterVerifyKey extends VerifyKey { super(key); } + public void clearSubKeys() { + subkeys.clear(); + } + public VerifyKey getValidSubKey() { return subkeys.getFirst(); } @@ -41,8 +45,4 @@ public class MasterVerifyKey extends VerifyKey { subkeys.addLast(key); } - - public void clearSubKeys() { - subkeys.clear(); - } } diff --git a/opretj/src/main/java/org/tcpid/key/VerifyKey.java b/opretj/src/main/java/org/tcpid/key/VerifyKey.java index f06a6cb..633870a 100644 --- a/opretj/src/main/java/org/tcpid/key/VerifyKey.java +++ b/opretj/src/main/java/org/tcpid/key/VerifyKey.java @@ -37,14 +37,6 @@ public class VerifyKey implements Comparable { private boolean revoked; private MasterVerifyKey masterkey; - public MasterVerifyKey getMasterkey() { - return masterkey; - } - - public void setMasterkey(MasterVerifyKey masterkey) { - this.masterkey = masterkey; - } - public VerifyKey(final byte[] key) { Util.checkLength(key, PUBLICKEY_BYTES); this.key = key; @@ -83,6 +75,10 @@ public class VerifyKey implements Comparable { return Arrays.equals(key, ((VerifyKey) o).key); } + public MasterVerifyKey getMasterkey() { + return masterkey; + } + public PublicKey getPublicKey() { final byte[] pk = Util.zeros(PUBLICKEY_BYTES); sodium(); @@ -98,6 +94,10 @@ public class VerifyKey implements Comparable { return revoked; } + public void setMasterkey(final MasterVerifyKey masterkey) { + this.masterkey = masterkey; + } + public void setRevoked(final boolean revoked) { if (this.revoked != true) { this.revoked = revoked; diff --git a/opretj/src/main/java/org/tcpid/opretj/OPRETECParser.java b/opretj/src/main/java/org/tcpid/opretj/OPRETECParser.java index 036c1aa..b74c4c0 100644 --- a/opretj/src/main/java/org/tcpid/opretj/OPRETECParser.java +++ b/opretj/src/main/java/org/tcpid/opretj/OPRETECParser.java @@ -20,10 +20,13 @@ import org.bitcoinj.script.ScriptBuilder; import org.bitcoinj.utils.ListenerRegistration; import org.bitcoinj.utils.Threading; import org.libsodium.jni.crypto.Box; +import org.libsodium.jni.crypto.Hash; import org.libsodium.jni.keys.KeyPair; import org.libsodium.jni.keys.PublicKey; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import org.tcpid.key.HMACSHA512256; +import org.tcpid.key.MasterSigningKey; import org.tcpid.key.SigningKey; import org.tcpid.key.VerifyKey; @@ -31,83 +34,11 @@ import com.google.common.primitives.Bytes; public class OPRETECParser extends OPRETBaseHandler { private static final Logger logger = LoggerFactory.getLogger(OPRETECParser.class); + public static final Hash HASH = new Hash(); + private static final List OPRET_MAGIC = Bytes.asList(Utils.HEX.decode("ec0f")); - protected final Map merkleHashMap = Collections.synchronizedMap(new HashMap<>()); - protected final Map transHashMap = Collections.synchronizedMap(new HashMap<>()); - protected final Map, List> verifyKeys = Collections.synchronizedMap(new HashMap<>()); - private final CopyOnWriteArrayList> opReturnChangeListeners = new CopyOnWriteArrayList<>(); - - /** - * Adds an event listener object. Methods on this object are called when - * scripts watched by this wallet change. The listener is executed by the - * given executor. - */ - public void addOPRETECRevokeEventListener(final OPRETECEventListener listener) { - // This is thread safe, so we don't need to take the lock. - opReturnChangeListeners.add(new ListenerRegistration(listener, Threading.SAME_THREAD)); - } - - private static byte[] doubleDec(final PublicKey MK, final PublicKey VK, final byte[] cipher, final byte[] nonce) { - - final KeyPair Epair = new KeyPair(Arrays.copyOfRange( - Sha256Hash.of(Bytes.concat(nonce, VK.toBytes(), MK.toBytes())).getBytes(), 0, SECRETKEY_BYTES)); - - final Box boxVK = new Box(VK, Epair.getPrivateKey()); - - final byte[] nonceVK = Arrays.copyOfRange( - Sha256Hash.of(Bytes.concat(nonce, Epair.getPrivateKey().toBytes(), VK.toBytes())).getBytes(), 0, - NONCE_BYTES); - - final byte[] cipherMK = boxVK.decrypt(nonceVK, cipher); - - final Box boxMK = new Box(MK, Epair.getPrivateKey()); - - final byte[] nonceMK = Arrays.copyOfRange( - Sha256Hash.of(Bytes.concat(nonce, Epair.getPrivateKey().toBytes(), MK.toBytes())).getBytes(), 0, - NONCE_BYTES); - - final byte[] clear = boxMK.decrypt(nonceMK, cipherMK); - - return clear; - } - - private static byte[] doubleEnc(final KeyPair MKpair, final KeyPair VKpair, final byte[] clear, - final byte[] nonce) { - - final KeyPair Epair = new KeyPair(Arrays.copyOfRange(Sha256Hash - .of(Bytes.concat(nonce, VKpair.getPublicKey().toBytes(), MKpair.getPublicKey().toBytes())).getBytes(), - 0, SECRETKEY_BYTES)); - - final Box boxMK = new Box(Epair.getPublicKey(), MKpair.getPrivateKey()); - - final byte[] nonceMK = Arrays.copyOfRange(Sha256Hash - .of(Bytes.concat(nonce, Epair.getPrivateKey().toBytes(), MKpair.getPublicKey().toBytes())).getBytes(), - 0, NONCE_BYTES); - - final byte[] cipherMK = boxMK.encrypt(nonceMK, clear); - - final Box boxVK = new Box(Epair.getPublicKey(), VKpair.getPrivateKey()); - - final byte[] nonceVK = Arrays.copyOfRange(Sha256Hash - .of(Bytes.concat(nonce, Epair.getPrivateKey().toBytes(), VKpair.getPublicKey().toBytes())).getBytes(), - 0, NONCE_BYTES); - - final byte[] cipherVK = boxVK.encrypt(nonceVK, cipherMK); - - return cipherVK; - } - - public static Script getRevokeScript(SigningKey key) { - final byte[] revokemsg = Bytes.concat("Revoke ".getBytes(), key.getVerifyKey().toHash()); - final byte[] sig = key.sign(revokemsg); - - final Script script = new ScriptBuilder().op(OP_RETURN).data(Utils.HEX.decode("ec0f")).data(sig) - .data(key.getVerifyKey().getShortHash()).build(); - return script; - } - - public static boolean checkKeyforRevoke(VerifyKey k, final byte[] sig) { + public static boolean checkKeyforRevoke(final VerifyKey k, final byte[] sig) { logger.debug("CHECKING REVOKE PKHASH {} - SIG {}", Utils.HEX.encode(k.toHash()), Utils.HEX.encode(sig)); final byte[] revokemsg = Bytes.concat("Revoke ".getBytes(), k.toHash()); @@ -123,23 +54,88 @@ public class OPRETECParser extends OPRETBaseHandler { } } - public boolean cryptoSelfTest() { - final SigningKey sk = new SigningKey(); - final VerifyKey vk = sk.getVerifyKey(); + private static byte[] doubleDec(final PublicKey MK, final PublicKey VK, final byte[] cipher, final byte[] nonce) { - final SigningKey msk = new SigningKey(); + final KeyPair Epair = new KeyPair(HMACSHA512256.of(MK.toBytes(), Bytes.concat(nonce, VK.toBytes()))); - final KeyPair mkpair = msk.getKeyPair(); - final KeyPair vkpair = sk.getKeyPair(); - final byte[] nonce = Arrays.copyOfRange(Sha256Hash.hash("TEST".getBytes()), 0, 8); - final byte[] cipher = doubleEnc(mkpair, vkpair, "TEST".getBytes(), nonce); - // System.err.println("Cipher len: " + cipher.length); - try { - final byte[] chk = doubleDec(msk.getVerifyKey().getPublicKey(), vk.getPublicKey(), cipher, nonce); - return Arrays.equals(chk, "TEST".getBytes()); - } catch (final Exception e) { - return false; + final Box boxVK = new Box(VK, Epair.getPrivateKey()); + + final byte[] nonceVK = Arrays.copyOfRange( + HMACSHA512256.of(VK.toBytes(), Bytes.concat(nonce, Epair.getPrivateKey().toBytes())), 0, NONCE_BYTES); + + final byte[] cipherMK = boxVK.decrypt(nonceVK, cipher); + + final Box boxMK = new Box(MK, Epair.getPrivateKey()); + + final byte[] nonceMK = Arrays.copyOfRange( + HMACSHA512256.of(MK.toBytes(), Bytes.concat(nonce, Epair.getPrivateKey().toBytes())), 0, NONCE_BYTES); + + final byte[] clear = boxMK.decrypt(nonceMK, cipherMK); + + return clear; + } + + private static byte[] doubleEnc(final KeyPair MKpair, final KeyPair VKpair, final byte[] clear, + final byte[] nonce) { + + final KeyPair Epair = new KeyPair(HMACSHA512256.of(MKpair.getPublicKey().toBytes(), + Bytes.concat(nonce, VKpair.getPublicKey().toBytes()))); + + final Box boxMK = new Box(Epair.getPublicKey(), MKpair.getPrivateKey()); + + final byte[] nonceMK = Arrays.copyOfRange( + HMACSHA512256.of(MKpair.getPublicKey().toBytes(), Bytes.concat(nonce, Epair.getPrivateKey().toBytes())), + 0, NONCE_BYTES); + + final byte[] cipherMK = boxMK.encrypt(nonceMK, clear); + + final Box boxVK = new Box(Epair.getPublicKey(), VKpair.getPrivateKey()); + + final byte[] nonceVK = Arrays.copyOfRange( + HMACSHA512256.of(VKpair.getPublicKey().toBytes(), Bytes.concat(nonce, Epair.getPrivateKey().toBytes())), + 0, NONCE_BYTES); + + final byte[] cipherVK = boxVK.encrypt(nonceVK, cipherMK); + + return cipherVK; + } + + public static Script getRevokeScript(final SigningKey key) { + final byte[] revokemsg = Bytes.concat("Revoke ".getBytes(), key.getVerifyKey().toHash()); + final byte[] sig = key.sign(revokemsg); + + final Script script = new ScriptBuilder().op(OP_RETURN).data(Utils.HEX.decode("ec0f")).data(sig) + .data(key.getVerifyKey().getShortHash()).build(); + return script; + } + + protected final Map merkleHashMap = Collections.synchronizedMap(new HashMap<>()); + + protected final Map transHashMap = Collections.synchronizedMap(new HashMap<>()); + + protected final Map, List> verifyKeys = Collections.synchronizedMap(new HashMap<>()); + + private final CopyOnWriteArrayList> opReturnChangeListeners = new CopyOnWriteArrayList<>(); + + /** + * Adds an event listener object. Methods on this object are called when + * scripts watched by this wallet change. The listener is executed by the + * given executor. + */ + public void addOPRETECRevokeEventListener(final OPRETECEventListener listener) { + // This is thread safe, so we don't need to take the lock. + opReturnChangeListeners.add(new ListenerRegistration(listener, Threading.SAME_THREAD)); + } + + public void addVerifyKey(final VerifyKey key, final long earliestTime) { + final List hash = Bytes.asList(key.getShortHash()); + if (!verifyKeys.containsKey(hash)) { + verifyKeys.put(hash, new ArrayList()); } + + verifyKeys.get(hash).add(key); + logger.debug("Adding pkhash {}", key.getShortHash()); + addOPRET(key.getShortHash(), earliestTime); } private boolean checkData(final OPRETTransaction t) { @@ -172,6 +168,48 @@ public class OPRETECParser extends OPRETBaseHandler { return handleRevoke(t); } + public boolean cryptoSelfTest() { + if (NONCE_BYTES > HMACSHA512256.HMACSHA512256_BYTES) { + logger.error("NONCE_BYTES > HMACSHA512256.HMACSHA512256_BYTES: {} > {}", NONCE_BYTES, + HMACSHA512256.HMACSHA512256_BYTES); + return false; + } + // TODO: test assert(HMACSHA512_KEYBYTES == SECRETKEY_BYTES) + if (SECRETKEY_BYTES != HMACSHA512256.HMACSHA512256_BYTES) { + logger.error("SECRETKEY_BYTES != HMACSHA512256.HMACSHA512256_BYTES: {} > {}", SECRETKEY_BYTES, + HMACSHA512256.HMACSHA512256_BYTES); + return false; + } + + final MasterSigningKey msk = new MasterSigningKey(HASH.sha256("TESTSEED".getBytes())); + if (!Arrays.equals(Utils.HEX.decode("4071b2b3db7cc7aecd0b23608e96f44f08463ea0ee0a0c12f5fa21ff449deb55"), + msk.toBytes())) { + logger.error("MasterSigningKey(HASH.sha256('TESTSEED'.getBytes())) test failed"); + return false; + } + + if (!Arrays.equals(Utils.HEX.decode("00cb0c8748318d27eab65159a2261c028d764c1154fc302b9b046aa2bbefab27"), + msk.getSubKey(1L).getSubKey(2L).getSubKey(3L).getSubKey(4L).toBytes())) { + logger.error("MasterSigningKey subkey derivation failed"); + return false; + } + + final SigningKey subkey = new SigningKey(); + final VerifyKey vk = subkey.getVerifyKey(); + + final KeyPair mkpair = msk.getKeyPair(); + final KeyPair vkpair = subkey.getKeyPair(); + final byte[] nonce = Arrays.copyOfRange(HASH.sha256("TEST".getBytes()), 0, 8); + final byte[] cipher = doubleEnc(mkpair, vkpair, "TEST".getBytes(), nonce); + try { + final byte[] chk = doubleDec(msk.getVerifyKey().getPublicKey(), vk.getPublicKey(), cipher, nonce); + return Arrays.equals(chk, "TEST".getBytes()); + } catch (final Exception e) { + logger.error("doubleEnc -> doubleDec failed!"); + return false; + } + } + private boolean handleRevoke(final OPRETTransaction t) { final List pkhash = t.opretData.get(2); final byte[] sig = Bytes.toArray(t.opretData.get(1)); @@ -201,15 +239,18 @@ public class OPRETECParser extends OPRETBaseHandler { checkData(t); } - public void addVerifyKey(final VerifyKey key, final long earliestTime) { - final List hash = Bytes.asList(key.getShortHash()); - if (!verifyKeys.containsKey(hash)) { - verifyKeys.put(hash, new ArrayList()); + protected void queueOnOPRETRevoke(final VerifyKey key) { + for (final ListenerRegistration registration : opReturnChangeListeners) { + registration.executor.execute(() -> registration.listener.onOPRETRevoke(key)); } + } - verifyKeys.get(hash).add(key); - logger.debug("Adding pkhash {}", key.getShortHash()); - addOPRET(key.getShortHash(), earliestTime); + /** + * Removes the given event listener object. Returns true if the listener was + * removed, false if that listener was never added. + */ + public boolean removeOPRETECRevokeEventListener(final OPRETECEventListener listener) { + return ListenerRegistration.removeFromList(listener, opReturnChangeListeners); } public void removeVerifyKey(final VerifyKey key) { @@ -223,18 +264,4 @@ public class OPRETECParser extends OPRETBaseHandler { removeOPRET(key.getShortHash()); } - - protected void queueOnOPRETRevoke(VerifyKey key) { - for (final ListenerRegistration registration : opReturnChangeListeners) { - registration.executor.execute(() -> registration.listener.onOPRETRevoke(key)); - } - } - - /** - * Removes the given event listener object. Returns true if the listener was - * removed, false if that listener was never added. - */ - public boolean removeOPRETECRevokeEventListener(final OPRETECEventListener listener) { - return ListenerRegistration.removeFromList(listener, opReturnChangeListeners); - } } diff --git a/opretj/src/main/java/org/tcpid/opretj/OPRETHandlerInterface.java b/opretj/src/main/java/org/tcpid/opretj/OPRETHandlerInterface.java index 90ae75f..d642653 100644 --- a/opretj/src/main/java/org/tcpid/opretj/OPRETHandlerInterface.java +++ b/opretj/src/main/java/org/tcpid/opretj/OPRETHandlerInterface.java @@ -18,8 +18,8 @@ public interface OPRETHandlerInterface { // void removeOPRET(byte[] magic); - boolean removeOPRETChangeEventListener(OPRETChangeEventListener listener); - void pushTransaction(OPRETTransaction t); + boolean removeOPRETChangeEventListener(OPRETChangeEventListener listener); + } diff --git a/opretj/src/main/java/org/tcpid/opretj/OPRETTransaction.java b/opretj/src/main/java/org/tcpid/opretj/OPRETTransaction.java index aa31ff3..a82603a 100644 --- a/opretj/src/main/java/org/tcpid/opretj/OPRETTransaction.java +++ b/opretj/src/main/java/org/tcpid/opretj/OPRETTransaction.java @@ -29,7 +29,7 @@ public class OPRETTransaction implements Serializable { return partialMerkleTree; } - public void setPartialMerkleTree(PartialMerkleTree partialMerkleTree) { + public void setPartialMerkleTree(final PartialMerkleTree partialMerkleTree) { this.partialMerkleTree = partialMerkleTree; } diff --git a/pom.xml b/pom.xml index da708fa..8b99d7b 100644 --- a/pom.xml +++ b/pom.xml @@ -2,7 +2,7 @@ 4.0.0 org.tcpid opret-parent - 0.0.1-SNAPSHOT + 0.0.2-SNAPSHOT pom opretj