Skip to content

Commit 27fc6e0

Browse files
Implement DistributedTransactionManager
1 parent 21b6e77 commit 27fc6e0

7 files changed

+386
-46
lines changed

pom.xml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,7 @@
7171
<dependency>
7272
<groupId>com.github.TIHBS</groupId>
7373
<artifactId>blockchain-access-layer-api</artifactId>
74-
<version>1.0.7</version>
74+
<version>${adapter.api.version}</version>
7575
</dependency>
7676
<dependency>
7777
<groupId>org.projectlombok</groupId>
@@ -150,6 +150,7 @@
150150
<jersey.version>2.9.1</jersey.version>
151151
<jackson.version>[2.9.9.2,)</jackson.version>
152152
<jsonrpc.version>0.10</jsonrpc.version>
153+
<adapter.api.version>feature~tccsci-1.0.6-gea834b9-12</adapter.api.version>
153154
<org.slf4j>1.7.25</org.slf4j>
154155
<ch.qos.logback.logback-classic.version>1.2.3</ch.qos.logback.logback-classic.version>
155156
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>

src/main/java/blockchains/iaas/uni/stuttgart/de/management/BlockchainManager.java

Lines changed: 77 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020

2121
import blockchains.iaas.uni.stuttgart.de.adaptation.AdapterManager;
2222
import blockchains.iaas.uni.stuttgart.de.api.exceptions.*;
23+
import blockchains.iaas.uni.stuttgart.de.api.model.*;
2324
import blockchains.iaas.uni.stuttgart.de.management.callback.CallbackManager;
2425
import blockchains.iaas.uni.stuttgart.de.management.callback.CamundaMessageTranslator;
2526
import blockchains.iaas.uni.stuttgart.de.management.callback.ScipMessageTranslator;
@@ -31,12 +32,8 @@
3132
import blockchains.iaas.uni.stuttgart.de.management.model.Subscription;
3233
import blockchains.iaas.uni.stuttgart.de.management.model.SubscriptionKey;
3334
import blockchains.iaas.uni.stuttgart.de.management.model.SubscriptionType;
34-
import blockchains.iaas.uni.stuttgart.de.api.model.Parameter;
35-
import blockchains.iaas.uni.stuttgart.de.api.model.QueryResult;
36-
import blockchains.iaas.uni.stuttgart.de.api.model.TimeFrame;
37-
import blockchains.iaas.uni.stuttgart.de.api.model.Transaction;
38-
import blockchains.iaas.uni.stuttgart.de.api.model.TransactionState;
3935
import com.google.common.base.Strings;
36+
import io.reactivex.Observable;
4037
import io.reactivex.disposables.Disposable;
4138
import org.slf4j.Logger;
4239
import org.slf4j.LoggerFactory;
@@ -366,42 +363,33 @@ public void invokeSmartContractFunction(
366363
final String correlationId,
367364
final String signature) throws BalException {
368365

369-
// Validate scip parameters!
370-
if (Strings.isNullOrEmpty(blockchainIdentifier)
371-
|| Strings.isNullOrEmpty(smartContractPath)
372-
|| Strings.isNullOrEmpty(functionIdentifier)
373-
|| timeoutMillis < 0
374-
|| MathUtils.doubleCompare(requiredConfidence, 0.0) < 0
375-
|| MathUtils.doubleCompare(requiredConfidence, 100.0) > 0) {
376-
throw new InvalidScipParameterException();
377-
}
378-
379-
final AdapterManager adapterManager = AdapterManager.getInstance();
380-
final double minimumConfidenceAsProbability = requiredConfidence / 100.0;
381-
final BlockchainAdapter adapter = adapterManager.getAdapter(blockchainIdentifier);
382-
final CompletableFuture<Transaction> future = adapter.invokeSmartContract(smartContractPath,
383-
functionIdentifier, inputs, outputs, minimumConfidenceAsProbability, timeoutMillis);
366+
final CompletableFuture<Transaction> future = this.invokeSmartContractFunction(blockchainIdentifier, smartContractPath,
367+
functionIdentifier, inputs, outputs, requiredConfidence, timeoutMillis, signature);
384368

385369
future.
386370
thenAccept(tx -> {
387371
if (tx != null) {
388-
if (tx.getState() == TransactionState.CONFIRMED || tx.getState() == TransactionState.RETURN_VALUE) {
389-
CallbackManager.getInstance().sendCallback(callbackUrl,
390-
ScipMessageTranslator.getInvocationResponseMessage(
391-
correlationId,
392-
tx.getReturnValues()));
393-
} else {// it is NOT_FOUND (it was dropped from the system due to invalidation) or ERRORED
394-
if (tx.getState() == TransactionState.NOT_FOUND) {
395-
CallbackManager.getInstance().sendCallback(callbackUrl,
396-
ScipMessageTranslator.getAsynchronousErrorResponseMessage(
397-
correlationId,
398-
new TransactionNotFoundException("The transaction associated with a function invocation is invalidated after it was mined.")));
399-
} else {
372+
if (callbackUrl != null) {
373+
if (tx.getState() == TransactionState.CONFIRMED || tx.getState() == TransactionState.RETURN_VALUE) {
400374
CallbackManager.getInstance().sendCallback(callbackUrl,
401-
ScipMessageTranslator.getAsynchronousErrorResponseMessage(
375+
ScipMessageTranslator.getInvocationResponseMessage(
402376
correlationId,
403-
new InvokeSmartContractFunctionFailure("The smart contract function invocation reported an error.")));
377+
tx.getReturnValues()));
378+
} else {// it is NOT_FOUND (it was dropped from the system due to invalidation) or ERRORED
379+
if (tx.getState() == TransactionState.NOT_FOUND) {
380+
CallbackManager.getInstance().sendCallback(callbackUrl,
381+
ScipMessageTranslator.getAsynchronousErrorResponseMessage(
382+
correlationId,
383+
new TransactionNotFoundException("The transaction associated with a function invocation is invalidated after it was mined.")));
384+
} else {
385+
CallbackManager.getInstance().sendCallback(callbackUrl,
386+
ScipMessageTranslator.getAsynchronousErrorResponseMessage(
387+
correlationId,
388+
new InvokeSmartContractFunctionFailure("The smart contract function invocation reported an error.")));
389+
}
404390
}
391+
} else {
392+
log.info("callbackUrl is null");
405393
}
406394
} else {
407395
log.info("resulting transaction is null");
@@ -414,6 +402,9 @@ public void invokeSmartContractFunction(
414402
CallbackManager.getInstance().sendCallback(callbackUrl,
415403
ScipMessageTranslator.getAsynchronousErrorResponseMessage(correlationId, (BalException) e.getCause()));
416404

405+
if (e instanceof ManualUnsubscriptionException || e.getCause() instanceof ManualUnsubscriptionException) {
406+
log.info("Manual unsubscription of SC invocation!");
407+
}
417408
// ManualUnsubscriptionException is also captured here
418409
return null;
419410
}).
@@ -427,6 +418,33 @@ public void invokeSmartContractFunction(
427418
SubscriptionManager.getInstance().createSubscription(correlationId, blockchainIdentifier, smartContractPath, subscription);
428419
}
429420

421+
public CompletableFuture<Transaction> invokeSmartContractFunction(
422+
final String blockchainIdentifier,
423+
final String smartContractPath,
424+
final String functionIdentifier,
425+
final List<Parameter> inputs,
426+
final List<Parameter> outputs,
427+
final double requiredConfidence,
428+
final long timeoutMillis,
429+
final String signature) throws BalException {
430+
431+
// Validate scip parameters!
432+
if (Strings.isNullOrEmpty(blockchainIdentifier)
433+
|| Strings.isNullOrEmpty(smartContractPath)
434+
|| Strings.isNullOrEmpty(functionIdentifier)
435+
|| timeoutMillis < 0
436+
|| MathUtils.doubleCompare(requiredConfidence, 0.0) < 0
437+
|| MathUtils.doubleCompare(requiredConfidence, 100.0) > 0) {
438+
throw new InvalidScipParameterException();
439+
}
440+
441+
final AdapterManager adapterManager = AdapterManager.getInstance();
442+
final double minimumConfidenceAsProbability = requiredConfidence / 100.0;
443+
final BlockchainAdapter adapter = adapterManager.getAdapter(blockchainIdentifier);
444+
return adapter.invokeSmartContract(smartContractPath,
445+
functionIdentifier, inputs, outputs, minimumConfidenceAsProbability, timeoutMillis);
446+
}
447+
430448
public void subscribeToEvent(
431449
final String blockchainIdentifier,
432450
final String smartContractPath,
@@ -437,21 +455,13 @@ public void subscribeToEvent(
437455
final String callbackUrl,
438456
final String correlationIdentifier) {
439457

440-
// Validate scip parameters!
441-
if (Strings.isNullOrEmpty(blockchainIdentifier)
442-
|| Strings.isNullOrEmpty(smartContractPath)
443-
|| Strings.isNullOrEmpty(eventIdentifier)
444-
|| MathUtils.doubleCompare(degreeOfConfidence, 0.0) < 0
445-
|| MathUtils.doubleCompare(degreeOfConfidence, 100.0) > 0) {
446-
throw new InvalidScipParameterException();
447-
}
448458

449-
final double minimumConfidenceAsProbability = degreeOfConfidence / 100.0;
450459

451460
// first, we cancel previous identical subscriptions.
452461
this.cancelEventSubscriptions(blockchainIdentifier, smartContractPath, correlationIdentifier, eventIdentifier, outputParameters);
453-
Disposable result = AdapterManager.getInstance().getAdapter(blockchainIdentifier)
454-
.subscribeToEvent(smartContractPath, eventIdentifier, outputParameters, minimumConfidenceAsProbability, filter)
462+
463+
464+
Disposable result = this.subscribeToEvent(blockchainIdentifier, smartContractPath, eventIdentifier, outputParameters, degreeOfConfidence, filter)
455465
.doFinally(() -> {
456466
// remove subscription from subscription list
457467
SubscriptionManager.getInstance().removeSubscription(correlationIdentifier, blockchainIdentifier, smartContractPath);
@@ -471,6 +481,28 @@ public void subscribeToEvent(
471481
SubscriptionManager.getInstance().createSubscription(correlationIdentifier, blockchainIdentifier, smartContractPath, subscription);
472482
}
473483

484+
public Observable<Occurrence> subscribeToEvent(String blockchainIdentifier,
485+
final String smartContractPath,
486+
final String eventIdentifier,
487+
final List<Parameter> outputParameters,
488+
final double degreeOfConfidence,
489+
final String filter) {
490+
// Validate scip parameters!
491+
if (Strings.isNullOrEmpty(blockchainIdentifier)
492+
|| Strings.isNullOrEmpty(smartContractPath)
493+
|| Strings.isNullOrEmpty(eventIdentifier)
494+
|| MathUtils.doubleCompare(degreeOfConfidence, 0.0) < 0
495+
|| MathUtils.doubleCompare(degreeOfConfidence, 100.0) > 0) {
496+
throw new InvalidScipParameterException();
497+
}
498+
499+
final double minimumConfidenceAsProbability = degreeOfConfidence / 100.0;
500+
501+
return AdapterManager.getInstance().getAdapter(blockchainIdentifier)
502+
.subscribeToEvent(smartContractPath, eventIdentifier, outputParameters, minimumConfidenceAsProbability, filter);
503+
}
504+
505+
474506
public void cancelEventSubscriptions(String blockchainId, String smartContractId, String correlationId, String eventIdentifier, List<Parameter> parameters) {
475507
// Validate scip parameters!
476508
if (Strings.isNullOrEmpty(blockchainId) || Strings.isNullOrEmpty(smartContractId)) {
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
package blockchains.iaas.uni.stuttgart.de.management.model;
2+
3+
import lombok.AllArgsConstructor;
4+
import lombok.Getter;
5+
import lombok.Setter;
6+
7+
import java.util.ArrayList;
8+
import java.util.List;
9+
import java.util.UUID;
10+
11+
@Setter
12+
@Getter
13+
public class DistributedTransaction {
14+
private final UUID id;
15+
private final List<String> blockchainIds;
16+
private DistributedTransactionState state;
17+
private DistributedTransactionVerdict verdict;
18+
private int yes;
19+
20+
public DistributedTransaction(UUID id) {
21+
this.id = id;
22+
this.blockchainIds = new ArrayList<>();
23+
this.state = DistributedTransactionState.AWAITING_REQUESTS;
24+
this.verdict = DistributedTransactionVerdict.NOT_DECIDED;
25+
}
26+
27+
public DistributedTransaction() {
28+
this(UUID.randomUUID());
29+
}
30+
31+
public void addBlockchainId(String blockchainId) {
32+
this.blockchainIds.add(blockchainId);
33+
}
34+
35+
}
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
package blockchains.iaas.uni.stuttgart.de.management.model;
2+
3+
public enum DistributedTransactionState {
4+
AWAITING_REQUESTS,
5+
AWAITING_VOTES,
6+
ABORTED,
7+
COMMITTED
8+
}
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
package blockchains.iaas.uni.stuttgart.de.management.model;
2+
3+
public enum DistributedTransactionVerdict {
4+
NOT_DECIDED,
5+
COMMIT,
6+
ABORT
7+
}

0 commit comments

Comments
 (0)