Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

chore(src/main): bunch of internal enhancements #30

Merged
merged 2 commits into from Jun 2, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
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);
}

}