Skip to content

Commit

Permalink
Merge pull request #30 from codenotary/chore_enhancements
Browse files Browse the repository at this point in the history
chore(src/main): bunch of internal enhancements
  • Loading branch information
jeroiraz committed Jun 2, 2022
2 parents d1ccece + 6e5e504 commit c16d55f
Show file tree
Hide file tree
Showing 17 changed files with 179 additions and 130 deletions.
4 changes: 2 additions & 2 deletions README.md
Expand Up @@ -55,12 +55,12 @@ Just include immudb4j as a dependency in your project:
<dependency>
<groupId>io.codenotary</groupId>
<artifactId>immudb4j</artifactId>
<version>0.9.10.0</version>
<version>0.9.10.2</version>
</dependency>
```
- if using Gradle:
```groovy
compile 'io.codenotary:immudb4j:0.9.10.0'
compile 'io.codenotary:immudb4j:0.9.10.2'
```

`immudb4j` is currently hosted on both [Maven Central] and [Github Packages].
Expand Down
11 changes: 3 additions & 8 deletions src/main/java/io/codenotary/immudb4j/FileImmuStateHolder.java
Expand Up @@ -15,13 +15,8 @@
*/
package io.codenotary.immudb4j;

import io.codenotary.immudb4j.crypto.CryptoUtils;

import java.io.BufferedWriter;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
Expand Down Expand Up @@ -71,14 +66,14 @@ public synchronized ImmuState getState(String serverUuid, String database) {
@Override
public synchronized void setState(String serverUuid, ImmuState state) throws IllegalStateException {

ImmuState currentState = stateHolder.getState(serverUuid, state.database);
if (currentState != null && currentState.txId >= state.txId) {
ImmuState currentState = stateHolder.getState(serverUuid, state.getDatabase());
if (currentState != null && currentState.getTxId() >= state.getTxId()) {
return;
}

stateHolder.setState(serverUuid, state);

Path newStateFile = statesFolder.resolve("state_" + serverUuid + "_" + state.database + "_" + System.nanoTime());
Path newStateFile = statesFolder.resolve("state_" + serverUuid + "_" + state.getDatabase() + "_" + System.nanoTime());

if (Files.exists(newStateFile)) {
throw new RuntimeException("Failed attempting to create a new state file. Please retry.");
Expand Down
76 changes: 43 additions & 33 deletions src/main/java/io/codenotary/immudb4j/ImmuClient.java
Expand Up @@ -142,7 +142,7 @@ public synchronized void logout() {
* Get the locally saved state of the current database.
* If nothing exists already, it is fetched from the server and save it locally.
*/
public ImmuState state() {
public ImmuState state() throws VerificationException {
ImmuState state = stateHolder.getState(currentServerUuid, currentDb);
if (state == null) {
state = currentState();
Expand All @@ -156,14 +156,14 @@ public ImmuState state() {
* It may throw a RuntimeException if server's state signature verification fails
* (if this feature is enabled on the client side, at least).
*/
public ImmuState currentState() {
public ImmuState currentState() throws VerificationException {
final Empty empty = com.google.protobuf.Empty.getDefaultInstance();
final ImmudbProto.ImmutableState state = getStub().currentState(empty);

final ImmuState immuState = ImmuState.valueOf(state);

if (!immuState.checkSignature(serverSigningKey)) {
throw new RuntimeException("State signature verification failed");
throw new VerificationException("State signature verification failed");
}

return immuState;
Expand Down Expand Up @@ -349,10 +349,20 @@ public Entry verifiedGetAtRevision(byte[] key, long rev) throws KeyNotFoundExcep
private Entry verifiedGet(ImmudbProto.KeyRequest keyReq, ImmuState state) throws KeyNotFoundException, VerificationException {
final ImmudbProto.VerifiableGetRequest vGetReq = ImmudbProto.VerifiableGetRequest.newBuilder()
.setKeyRequest(keyReq)
.setProveSinceTx(state.txId)
.setProveSinceTx(state.getTxId())
.build();

final ImmudbProto.VerifiableEntry vEntry = getStub().verifiableGet(vGetReq);
final ImmudbProto.VerifiableEntry vEntry;

try {
vEntry = getStub().verifiableGet(vGetReq);
} catch (StatusRuntimeException e) {
if (e.getMessage().contains("key not found")) {
throw new KeyNotFoundException();
}

throw e;
}

final InclusionProof inclusionProof = InclusionProof.valueOf(vEntry.getInclusionProof());
final DualProof dualProof = DualProof.valueOf(vEntry.getVerifiableTx().getDualProof());
Expand All @@ -365,27 +375,27 @@ private Entry verifiedGet(ImmudbProto.KeyRequest keyReq, ImmuState state) throws
final Entry entry = Entry.valueOf(vEntry.getEntry());

if (entry.getReferenceBy() == null && !Arrays.equals(keyReq.getKey().toByteArray(), entry.getKey())) {
throw new RuntimeException("Data is corrupted: entry does not belong to specified key");
throw new VerificationException("Data is corrupted: entry does not belong to specified key");
}

if (entry.getReferenceBy() != null && !Arrays.equals(keyReq.getKey().toByteArray(), entry.getReferenceBy().getKey())) {
throw new RuntimeException("Data is corrupted: entry does not belong to specified key");
throw new VerificationException("Data is corrupted: entry does not belong to specified key");
}

if (entry.getMetadata() != null && entry.getMetadata().deleted()) {
throw new RuntimeException("Data is corrupted: entry is marked as deleted");
throw new VerificationException("Data is corrupted: entry is marked as deleted");
}

if (keyReq.getAtTx() != 0 && entry.getTx() != keyReq.getAtTx()) {
throw new RuntimeException("Data is corrupted: entry does not belong to specified tx");
throw new VerificationException("Data is corrupted: entry does not belong to specified tx");
}

if (state.txId <= entry.getTx()) {
if (state.getTxId() <= entry.getTx()) {
final byte[] digest = vEntry.getVerifiableTx().getDualProof().getTargetTxHeader().getEH().toByteArray();
eh = CryptoUtils.digestFrom(digest);

sourceId = state.txId;
sourceAlh = CryptoUtils.digestFrom(state.txHash);
sourceId = state.getTxId();
sourceAlh = CryptoUtils.digestFrom(state.getTxHash());
targetId = entry.getTx();
targetAlh = dualProof.targetTxHeader.alh();
} else {
Expand All @@ -394,8 +404,8 @@ private Entry verifiedGet(ImmudbProto.KeyRequest keyReq, ImmuState state) throws

sourceId = entry.getTx();
sourceAlh = dualProof.sourceTxHeader.alh();
targetId = state.txId;
targetAlh = CryptoUtils.digestFrom(state.txHash);
targetId = state.getTxId();
targetAlh = CryptoUtils.digestFrom(state.getTxHash());
}

final byte[] kvDigest = entry.digestFor(vEntry.getVerifiableTx().getTx().getHeader().getVersion());
Expand All @@ -404,7 +414,7 @@ private Entry verifiedGet(ImmudbProto.KeyRequest keyReq, ImmuState state) throws
throw new VerificationException("Inclusion verification failed.");
}

if (state.txId > 0) {
if (state.getTxId() > 0) {
if (!CryptoUtils.verifyDualProof(
dualProof,
sourceId,
Expand All @@ -423,7 +433,7 @@ private Entry verifiedGet(ImmudbProto.KeyRequest keyReq, ImmuState state) throws
vEntry.getVerifiableTx().getSignature().toByteArray());

if (!newState.checkSignature(serverSigningKey)) {
throw new RuntimeException("State signature verification failed");
throw new VerificationException("State signature verification failed");
}

stateHolder.setState(currentServerUuid, newState);
Expand Down Expand Up @@ -622,7 +632,7 @@ public TxHeader verifiedSet(byte[] key, byte[] value) throws VerificationExcepti

final ImmudbProto.VerifiableSetRequest vSetReq = ImmudbProto.VerifiableSetRequest.newBuilder()
.setSetRequest(ImmudbProto.SetRequest.newBuilder().addKVs(kv).build())
.setProveSinceTx(state.txId)
.setProveSinceTx(state.getTxId())
.build();

final ImmudbProto.VerifiableTx vtx = getStub().verifiableSet(vSetReq);
Expand Down Expand Up @@ -660,7 +670,7 @@ public TxHeader verifiedSet(byte[] key, byte[] value) throws VerificationExcepti
final ImmuState newState = verifyDualProof(vtx, tx, state);

if (!newState.checkSignature(serverSigningKey)) {
throw new RuntimeException("State signature verification failed");
throw new VerificationException("State signature verification failed");
}

stateHolder.setState(currentServerUuid, newState);
Expand All @@ -685,7 +695,7 @@ public TxHeader verifiedSetReference(byte[] key, byte[] referencedKey, long atTx

final ImmudbProto.VerifiableReferenceRequest vRefReq = ImmudbProto.VerifiableReferenceRequest.newBuilder()
.setReferenceRequest(refReq)
.setProveSinceTx(state.txId)
.setProveSinceTx(state.getTxId())
.build();

final ImmudbProto.VerifiableTx vtx = getStub().verifiableSetReference(vRefReq);
Expand Down Expand Up @@ -728,7 +738,7 @@ public TxHeader verifiedSetReference(byte[] key, byte[] referencedKey, long atTx
final ImmuState newState = verifyDualProof(vtx, tx, state);

if (!newState.checkSignature(serverSigningKey)) {
throw new RuntimeException("State signature verification failed");
throw new VerificationException("State signature verification failed");
}

stateHolder.setState(currentServerUuid, newState);
Expand All @@ -739,12 +749,12 @@ public TxHeader verifiedSetReference(byte[] key, byte[] referencedKey, long atTx
private ImmuState verifyDualProof(ImmudbProto.VerifiableTx vtx, Tx tx, ImmuState state)
throws VerificationException {

final long sourceId = state.txId;
final long sourceId = state.getTxId();
final long targetId = tx.getHeader().getId();
final byte[] sourceAlh = CryptoUtils.digestFrom(state.txHash);
final byte[] sourceAlh = CryptoUtils.digestFrom(state.getTxHash());
final byte[] targetAlh = tx.getHeader().alh();

if (state.txId > 0) {
if (state.getTxId() > 0) {
if (!CryptoUtils.verifyDualProof(
DualProof.valueOf(vtx.getDualProof()),
sourceId,
Expand Down Expand Up @@ -815,7 +825,7 @@ public TxHeader verifiedZAdd(byte[] set, byte[] key, long atTx, double score) th

final ImmudbProto.VerifiableZAddRequest vZAddReq = ImmudbProto.VerifiableZAddRequest.newBuilder()
.setZAddRequest(zAddReq)
.setProveSinceTx(state.txId)
.setProveSinceTx(state.getTxId())
.build();

final ImmudbProto.VerifiableTx vtx = getStub().verifiableZAdd(vZAddReq);
Expand Down Expand Up @@ -854,7 +864,7 @@ public TxHeader verifiedZAdd(byte[] set, byte[] key, long atTx, double score) th
final ImmuState newState = verifyDualProof(vtx, tx, state);

if (!newState.checkSignature(serverSigningKey)) {
throw new RuntimeException("State signature verification failed");
throw new VerificationException("State signature verification failed");
}

stateHolder.setState(currentServerUuid, newState);
Expand Down Expand Up @@ -900,7 +910,7 @@ public Tx verifiedTxById(long txId) throws TxNotFoundException, VerificationExce
final ImmuState state = state();
final ImmudbProto.VerifiableTxRequest vTxReq = ImmudbProto.VerifiableTxRequest.newBuilder()
.setTx(txId)
.setProveSinceTx(state.txId)
.setProveSinceTx(state.getTxId())
.build();

final ImmudbProto.VerifiableTx vtx;
Expand All @@ -922,19 +932,19 @@ public Tx verifiedTxById(long txId) throws TxNotFoundException, VerificationExce
byte[] sourceAlh;
byte[] targetAlh;

if (state.txId <= txId) {
sourceId = state.txId;
sourceAlh = CryptoUtils.digestFrom(state.txHash);
if (state.getTxId() <= txId) {
sourceId = state.getTxId();
sourceAlh = CryptoUtils.digestFrom(state.getTxHash());
targetId = txId;
targetAlh = dualProof.targetTxHeader.alh();
} else {
sourceId = txId;
sourceAlh = dualProof.sourceTxHeader.alh();
targetId = state.txId;
targetAlh = CryptoUtils.digestFrom(state.txHash);
targetId = state.getTxId();
targetAlh = CryptoUtils.digestFrom(state.getTxHash());
}

if (state.txId > 0) {
if (state.getTxId() > 0) {
if (!CryptoUtils.verifyDualProof(
DualProof.valueOf(vtx.getDualProof()),
sourceId,
Expand All @@ -956,7 +966,7 @@ public Tx verifiedTxById(long txId) throws TxNotFoundException, VerificationExce
final ImmuState newState = new ImmuState(currentDb, targetId, targetAlh, vtx.getSignature().getSignature().toByteArray());

if (!newState.checkSignature(serverSigningKey)) {
throw new RuntimeException("State signature verification failed");
throw new VerificationException("State signature verification failed");
}

stateHolder.setState(currentServerUuid, newState);
Expand Down
27 changes: 21 additions & 6 deletions src/main/java/io/codenotary/immudb4j/ImmuState.java
Expand Up @@ -20,7 +20,6 @@
import java.nio.charset.StandardCharsets;
import java.security.PublicKey;
import java.security.Signature;
import java.util.Base64;

/**
* ImmuState represents the state within a database.
Expand All @@ -29,12 +28,12 @@
*/
public class ImmuState {

public final String database;
public final long txId;
public final byte[] txHash;
public final byte[] signature;
private final String database;
private final long txId;
private final byte[] txHash;
private final byte[] signature;

public ImmuState(String database, long txId, byte[] txHash, byte[] signature) {
ImmuState(String database, long txId, byte[] txHash, byte[] signature) {
this.database = database;
this.txId = txId;
this.txHash = txHash;
Expand Down Expand Up @@ -62,6 +61,22 @@ boolean checkSignature(PublicKey pubKey) {
return false;
}

public String getDatabase() {
return database;
}

public long getTxId() {
return txId;
}

public byte[] getTxHash() {
return txHash;
}

public byte[] getSignature() {
return signature;
}

private byte[] toBytes() {
byte[] b = new byte[4 + database.length() + 8 + Consts.SHA256_SIZE];
int i = 0;
Expand Down
8 changes: 4 additions & 4 deletions src/main/java/io/codenotary/immudb4j/KVMetadata.java
Expand Up @@ -37,7 +37,7 @@ public class KVMetadata {

private HashMap<Byte,MetadataAttribute> attributes;

public KVMetadata() {
private KVMetadata() {
attributes = new HashMap<Byte,MetadataAttribute>();
}

Expand All @@ -55,7 +55,7 @@ public static KVMetadata valueOf(ImmudbProto.KVMetadata md) {
return metadata;
}

public void asDeleted(boolean deleted) {
private void asDeleted(boolean deleted) {
if (!deleted) {
attributes.remove(deletedAttrCode);
return;
Expand All @@ -72,7 +72,7 @@ public boolean deleted() {
return attributes.containsKey(deletedAttrCode);
}

public void asNonIndexable(boolean nonIndexable) {
private void asNonIndexable(boolean nonIndexable) {
if (!nonIndexable) {
attributes.remove(nonIndexableAttrCode);
return;
Expand All @@ -89,7 +89,7 @@ public boolean nonIndexable() {
return attributes.containsKey(nonIndexableAttrCode);
}

public void expiresAt(long expirationTime) {
private void expiresAt(long expirationTime) {
ExpiresAtAttribute expiresAt;

if (attributes.containsKey(expiresAtAttrCode)) {
Expand Down
Expand Up @@ -20,5 +20,6 @@ public interface MetadataAttribute {
static final int AttrCodeSize = 1;

byte code();

byte[] serialize();
}
2 changes: 1 addition & 1 deletion src/main/java/io/codenotary/immudb4j/Reference.java
Expand Up @@ -22,7 +22,6 @@ public class Reference {
private long tx;
private byte[] key;
private long atTx;

private KVMetadata metadata;

private Reference() {}
Expand Down Expand Up @@ -51,6 +50,7 @@ public byte[] getKey() {
public long getAtTx() {
return atTx;
}

public KVMetadata getMetadata() {
return metadata;
}
Expand Down
Expand Up @@ -52,7 +52,7 @@ public ImmuState getState(String serverUuid, String database) {

@Override
public void setState(String serverUuid, ImmuState state) {
this.statesMap.put(serverUuid + "_" + state.database, state);
this.statesMap.put(serverUuid + "_" + state.getDatabase(), state);
}

}

0 comments on commit c16d55f

Please sign in to comment.