Merge branch 'master' into dynamic-loading

This commit is contained in:
sofusmortensen 2016-04-09 01:01:36 +02:00
commit d05e6bb6a4
106 changed files with 370 additions and 1029 deletions

View File

@ -24,6 +24,16 @@ Things you need to know:
* There will be a mailing list for discussion, brainstorming etc called [r3dlg-awg](https://groups.google.com/forum/#!forum/r3dlg-awg). * There will be a mailing list for discussion, brainstorming etc called [r3dlg-awg](https://groups.google.com/forum/#!forum/r3dlg-awg).
# License
This code is not yet released under a traditional open source license. Until it is, the following license applies:
_Copyright 2015 Distributed Ledger Group LLC. Distributed as Licensed Company IP to DLG Group Members
pursuant to the August 7, 2015 Advisory Services Agreement and subject to the Company IP License terms
set forth therein. Distributed as Non-Project IP to R3 LRC Members pursuant to their respective Member
and Services Agreements and subject to the Non-Project IP license terms. set forth therein. All other rights reserved._
# Instructions for installing prerequisite software # Instructions for installing prerequisite software
## JDK for Java 8 ## JDK for Java 8
@ -52,6 +62,7 @@ The code should build, the unit tests should show as all green.
You can catch up with the latest code by selecting "VCS -> Update Project" in the menu. You can catch up with the latest code by selecting "VCS -> Update Project" in the menu.
## IntelliJ Troubleshooting ## IntelliJ Troubleshooting
If on attempting to open the project, IntelliJ refuses because SDK was not selected, do the following: If on attempting to open the project, IntelliJ refuses because SDK was not selected, do the following:
Configure -> Project Defaults -> Project Structure Configure -> Project Defaults -> Project Structure
@ -66,6 +77,17 @@ click on New… next to the red <No SDK> symbol, and select JDK. It should then
Also select Project language level: as 8. Click OK. Open should now work. Also select Project language level: as 8. Click OK. Open should now work.
## Other troubleshooting
If you get an error about a missing Quasar agent, then your JVM is being invoked without a needed command line argument.
Make sure an argument like `-javaagent:lib/quasar.jar` is being passed to the invocation.
You may need/want to edit your default JUnit run config in IntelliJ to ensure that parameter is being set, along with
`-Dco.paralleluniverse.fibers.verifyInstrumentation` which is useful to catch mistakes. To do that, click the dropdown
in the toolbar and select "Edit configurations", then expand the defaults tree, then select JUnit and add the two
arguments to the VM options edit.
## Accessing Source Without an IDE ## Accessing Source Without an IDE
If you don't want to explore or modify the code in a local IDE, you can also just use the command line and a text editor: If you don't want to explore or modify the code in a local IDE, you can also just use the command line and a text editor:

View File

@ -160,6 +160,8 @@ task getIRSDemo(type: CreateStartScripts) {
// that have @Suspendable sub implementations. These tend to cause NPEs and are not caught by the verifier // that have @Suspendable sub implementations. These tend to cause NPEs and are not caught by the verifier
// NOTE: need to make sure the output isn't on the classpath or every other run it generates empty results, so // NOTE: need to make sure the output isn't on the classpath or every other run it generates empty results, so
// we explicitly delete to avoid that happening. We also need to turn off what seems to be a spurious warning in the IDE // we explicitly delete to avoid that happening. We also need to turn off what seems to be a spurious warning in the IDE
//
// TODO: Make this task incremental, as it can be quite slow.
//noinspection GroovyAssignabilityCheck //noinspection GroovyAssignabilityCheck
task quasarScan(dependsOn: ['classes', 'core:classes', 'contracts:classes']) << { task quasarScan(dependsOn: ['classes', 'core:classes', 'contracts:classes']) << {

View File

@ -1,11 +1,12 @@
import com.google.common.io.ByteStreams import com.google.common.io.ByteStreams
import java.nio.file.Files import java.nio.file.Files
import java.nio.file.Paths import java.nio.file.Paths
import java.nio.file.StandardCopyOption import java.nio.file.StandardCopyOption
import java.nio.file.attribute.FileTime import java.nio.file.attribute.FileTime
import java.util.zip.ZipEntry import java.util.zip.ZipEntry
import java.util.zip.ZipOutputStream
import java.util.zip.ZipFile import java.util.zip.ZipFile
import java.util.zip.ZipOutputStream
buildscript { buildscript {
repositories { repositories {
@ -37,7 +38,7 @@ class CanonicalizerPlugin implements Plugin<Project> {
output.setMethod(ZipOutputStream.DEFLATED) output.setMethod(ZipOutputStream.DEFLATED)
entries.each { entries.each {
def newEntry = new ZipEntry( it.name ) def newEntry = new ZipEntry(it.name)
newEntry.setLastModifiedTime(zeroTime) newEntry.setLastModifiedTime(zeroTime)
newEntry.setCreationTime(zeroTime) newEntry.setCreationTime(zeroTime)

View File

@ -1,10 +1,3 @@
/*
* Copyright 2015 Distributed Ledger Group LLC. Distributed as Licensed Company IP to DLG Group Members
* pursuant to the August 7, 2015 Advisory Services Agreement and subject to the Company IP License terms
* set forth therein.
*
* All other rights reserved.
*/
package contracts; package contracts;
import core.*; import core.*;
@ -19,7 +12,10 @@ import java.time.*;
*/ */
public interface ICommercialPaperState extends ContractState { public interface ICommercialPaperState extends ContractState {
ICommercialPaperState withOwner(PublicKey newOwner); ICommercialPaperState withOwner(PublicKey newOwner);
ICommercialPaperState withIssuance(PartyReference newIssuance); ICommercialPaperState withIssuance(PartyReference newIssuance);
ICommercialPaperState withFaceValue(Amount newFaceValue); ICommercialPaperState withFaceValue(Amount newFaceValue);
ICommercialPaperState withMaturityDate(Instant newMaturityDate); ICommercialPaperState withMaturityDate(Instant newMaturityDate);
} }

View File

@ -1,35 +1,22 @@
/*
* Copyright 2015 Distributed Ledger Group LLC. Distributed as Licensed Company IP to DLG Group Members
* pursuant to the August 7, 2015 Advisory Services Agreement and subject to the Company IP License terms
* set forth therein.
*
* All other rights reserved.
*/
package contracts; package contracts;
import core.*; import core.*;
import core.TransactionForVerification.InOutGroup; import core.TransactionForVerification.*;
import core.crypto.NullPublicKey; import core.crypto.*;
import core.crypto.SecureHash;
import core.node.services.*; import core.node.services.*;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.*;
import org.jetbrains.annotations.Nullable;
import java.security.PublicKey;
import java.time.Instant;
import java.util.List;
import static core.ContractsDSLKt.requireSingleCommand;
import static kotlin.collections.CollectionsKt.single;
import java.security.*;
import java.time.*;
import java.util.*;
import static core.ContractsDSLKt.*;
import static kotlin.collections.CollectionsKt.*;
/** /**
* This is a Java version of the CommercialPaper contract (chosen because it's simple). This demonstrates how the * This is a Java version of the CommercialPaper contract (chosen because it's simple). This demonstrates how the
* use of Kotlin for implementation of the framework does not impose the same language choice on contract developers. * use of Kotlin for implementation of the framework does not impose the same language choice on contract developers.
*
*/ */
public class JavaCommercialPaper implements Contract { public class JavaCommercialPaper implements Contract {
//public static SecureHash JCP_PROGRAM_ID = SecureHash.sha256("java commercial paper (this should be a bytecode hash)"); //public static SecureHash JCP_PROGRAM_ID = SecureHash.sha256("java commercial paper (this should be a bytecode hash)");
@ -41,7 +28,8 @@ public class JavaCommercialPaper implements Contract {
private Amount faceValue; private Amount faceValue;
private Instant maturityDate; private Instant maturityDate;
public State() {} // For serialization public State() {
} // For serialization
public State(PartyReference issuance, PublicKey owner, Amount faceValue, Instant maturityDate) { public State(PartyReference issuance, PublicKey owner, Amount faceValue, Instant maturityDate) {
this.issuance = issuance; this.issuance = issuance;
@ -135,6 +123,7 @@ public class JavaCommercialPaper implements Contract {
return obj instanceof Redeem; return obj instanceof Redeem;
} }
} }
public static class Issue extends Commands { public static class Issue extends Commands {
@Override @Override
public boolean equals(Object obj) { public boolean equals(Object obj) {
@ -175,15 +164,15 @@ public class JavaCommercialPaper implements Contract {
Instant time = timestampCommand.getBefore(); Instant time = timestampCommand.getBefore();
if (! time.isBefore(output.maturityDate)) { if (!time.isBefore(output.maturityDate)) {
throw new IllegalStateException("Failed Requirement: the maturity date is not in the past"); throw new IllegalStateException("Failed Requirement: the maturity date is not in the past");
} }
if (!cmd.getSigners().contains(output.issuance.getParty().getOwningKey())) { if (!cmd.getSigners().contains(output.issuance.getParty().getOwningKey())) {
throw new IllegalStateException("Failed Requirement: the issuance is signed by the claimed issuer of the paper"); throw new IllegalStateException("Failed Requirement: the issuance is signed by the claimed issuer of the paper");
} }
} } else {
else { // Everything else (Move, Redeem) requires inputs (they are not first to be actioned) // Everything else (Move, Redeem) requires inputs (they are not first to be actioned)
// There should be only a single input due to aggregation above // There should be only a single input due to aggregation above
State input = single(inputs); State input = single(inputs);
@ -198,9 +187,7 @@ public class JavaCommercialPaper implements Contract {
!output.getIssuance().equals(input.getIssuance()) || !output.getIssuance().equals(input.getIssuance()) ||
!output.getMaturityDate().equals(input.getMaturityDate())) !output.getMaturityDate().equals(input.getMaturityDate()))
throw new IllegalStateException("Failed requirement: the output state is the same as the input state except for owner"); throw new IllegalStateException("Failed requirement: the output state is the same as the input state except for owner");
} } else if (cmd.getValue() instanceof JavaCommercialPaper.Commands.Redeem) {
else if (cmd.getValue() instanceof JavaCommercialPaper.Commands.Redeem)
{
TimestampCommand timestampCommand = tx.getTimestampBy(DummyTimestampingAuthority.INSTANCE.getIdentity()); TimestampCommand timestampCommand = tx.getTimestampBy(DummyTimestampingAuthority.INSTANCE.getIdentity());
if (timestampCommand == null) if (timestampCommand == null)
throw new IllegalArgumentException("Failed Requirement: must be timestamped"); throw new IllegalArgumentException("Failed Requirement: must be timestamped");
@ -208,7 +195,7 @@ public class JavaCommercialPaper implements Contract {
Amount received = CashKt.sumCashBy(tx.getOutStates(), input.getOwner()); Amount received = CashKt.sumCashBy(tx.getOutStates(), input.getOwner());
if (! received.equals(input.getFaceValue())) if (!received.equals(input.getFaceValue()))
throw new IllegalStateException("Failed Requirement: received amount equals the face value"); throw new IllegalStateException("Failed Requirement: received amount equals the face value");
if (time.isBefore(input.getMaturityDate())) if (time.isBefore(input.getMaturityDate()))
throw new IllegalStateException("Failed requirement: the paper must have matured"); throw new IllegalStateException("Failed requirement: the paper must have matured");
@ -229,14 +216,14 @@ public class JavaCommercialPaper implements Contract {
} }
public TransactionBuilder generateIssue(@NotNull PartyReference issuance, @NotNull Amount faceValue, @Nullable Instant maturityDate) { public TransactionBuilder generateIssue(@NotNull PartyReference issuance, @NotNull Amount faceValue, @Nullable Instant maturityDate) {
State state = new State(issuance,issuance.getParty().getOwningKey(), faceValue, maturityDate); State state = new State(issuance, issuance.getParty().getOwningKey(), faceValue, maturityDate);
return new TransactionBuilder().withItems(state, new Command( new Commands.Issue(), issuance.getParty().getOwningKey())); return new TransactionBuilder().withItems(state, new Command(new Commands.Issue(), issuance.getParty().getOwningKey()));
} }
public void generateRedeem(TransactionBuilder tx, StateAndRef<State> paper, List<StateAndRef<Cash.State>> wallet) throws InsufficientBalanceException { public void generateRedeem(TransactionBuilder tx, StateAndRef<State> paper, List<StateAndRef<Cash.State>> wallet) throws InsufficientBalanceException {
new Cash().generateSpend(tx, paper.getState().getFaceValue(), paper.getState().getOwner(), wallet, null); new Cash().generateSpend(tx, paper.getState().getFaceValue(), paper.getState().getOwner(), wallet, null);
tx.addInputState(paper.getRef()); tx.addInputState(paper.getRef());
tx.addCommand(new Command( new Commands.Redeem(), paper.getState().getOwner())); tx.addCommand(new Command(new Commands.Redeem(), paper.getState().getOwner()));
} }
public void generateMove(TransactionBuilder tx, StateAndRef<State> paper, PublicKey newOwner) { public void generateMove(TransactionBuilder tx, StateAndRef<State> paper, PublicKey newOwner) {

View File

@ -1,11 +1,3 @@
/*
* Copyright 2015 Distributed Ledger Group LLC. Distributed as Licensed Company IP to DLG Group Members
* pursuant to the August 7, 2015 Advisory Services Agreement and subject to the Company IP License terms
* set forth therein.
*
* All other rights reserved.
*/
package contracts package contracts
import core.* import core.*
@ -246,10 +238,13 @@ class Cash : Contract {
/** Sums the cash states in the list that are owned by the given key, throwing an exception if there are none. */ /** Sums the cash states in the list that are owned by the given key, throwing an exception if there are none. */
fun Iterable<ContractState>.sumCashBy(owner: PublicKey) = filterIsInstance<Cash.State>().filter { it.owner == owner }.map { it.amount }.sumOrThrow() fun Iterable<ContractState>.sumCashBy(owner: PublicKey) = filterIsInstance<Cash.State>().filter { it.owner == owner }.map { it.amount }.sumOrThrow()
/** Sums the cash states in the list, throwing an exception if there are none. */ /** Sums the cash states in the list, throwing an exception if there are none. */
fun Iterable<ContractState>.sumCash() = filterIsInstance<Cash.State>().map { it.amount }.sumOrThrow() fun Iterable<ContractState>.sumCash() = filterIsInstance<Cash.State>().map { it.amount }.sumOrThrow()
/** Sums the cash states in the list, returning null if there are none. */ /** Sums the cash states in the list, returning null if there are none. */
fun Iterable<ContractState>.sumCashOrNull() = filterIsInstance<Cash.State>().map { it.amount }.sumOrNull() fun Iterable<ContractState>.sumCashOrNull() = filterIsInstance<Cash.State>().map { it.amount }.sumOrNull()
/** Sums the cash states in the list, returning zero of the given currency if there are none. */ /** Sums the cash states in the list, returning zero of the given currency if there are none. */
fun Iterable<ContractState>.sumCashOrZero(currency: Currency) = filterIsInstance<Cash.State>().map { it.amount }.sumOrZero(currency) fun Iterable<ContractState>.sumCashOrZero(currency: Currency) = filterIsInstance<Cash.State>().map { it.amount }.sumOrZero(currency)

View File

@ -1,11 +1,3 @@
/*
* Copyright 2015 Distributed Ledger Group LLC. Distributed as Licensed Company IP to DLG Group Members
* pursuant to the August 7, 2015 Advisory Services Agreement and subject to the Company IP License terms
* set forth therein.
*
* All other rights reserved.
*/
package contracts package contracts
import core.* import core.*
@ -59,6 +51,7 @@ class CommercialPaper : Contract {
// Although kotlin is smart enough not to need these, as we are using the ICommercialPaperState, we need to declare them explicitly for use later, // Although kotlin is smart enough not to need these, as we are using the ICommercialPaperState, we need to declare them explicitly for use later,
override fun withOwner(newOwner: PublicKey): ICommercialPaperState = copy(owner = newOwner) override fun withOwner(newOwner: PublicKey): ICommercialPaperState = copy(owner = newOwner)
override fun withIssuance(newIssuance: PartyReference): ICommercialPaperState = copy(issuance = newIssuance) override fun withIssuance(newIssuance: PartyReference): ICommercialPaperState = copy(issuance = newIssuance)
override fun withFaceValue(newFaceValue: Amount): ICommercialPaperState = copy(faceValue = newFaceValue) override fun withFaceValue(newFaceValue: Amount): ICommercialPaperState = copy(faceValue = newFaceValue)
override fun withMaturityDate(newMaturityDate: Instant): ICommercialPaperState = copy(maturityDate = newMaturityDate) override fun withMaturityDate(newMaturityDate: Instant): ICommercialPaperState = copy(maturityDate = newMaturityDate)

View File

@ -1,11 +1,3 @@
/*
* Copyright 2015 Distributed Ledger Group LLC. Distributed as Licensed Company IP to DLG Group Members
* pursuant to the August 7, 2015 Advisory Services Agreement and subject to the Company IP License terms
* set forth therein.
*
* All other rights reserved.
*/
package contracts package contracts
import core.* import core.*

View File

@ -1,11 +1,3 @@
/*
* Copyright 2015 Distributed Ledger Group LLC. Distributed as Licensed Company IP to DLG Group Members
* pursuant to the August 7, 2015 Advisory Services Agreement and subject to the Company IP License terms
* set forth therein.
*
* All other rights reserved.
*/
package contracts package contracts
import core.* import core.*

View File

@ -1,11 +1,3 @@
/*
* Copyright 2015 Distributed Ledger Group LLC. Distributed as Licensed Company IP to DLG Group Members
* pursuant to the August 7, 2015 Advisory Services Agreement and subject to the Company IP License terms
* set forth therein.
*
* All other rights reserved.
*/
package contracts package contracts
import core.* import core.*
@ -465,7 +457,8 @@ class InterestRateSwap() : Contract {
override val parties: Array<Party> override val parties: Array<Party>
get() = arrayOf(fixedLeg.fixedRatePayer, floatingLeg.floatingRatePayer) get() = arrayOf(fixedLeg.fixedRatePayer, floatingLeg.floatingRatePayer)
override fun withPublicKey(before: Party, after: PublicKey): State { // TODO: This changing of the public key violates the assumption that Party is a fixed identity key.
override fun withPublicKey(before: Party, after: PublicKey): DealState {
val newParty = Party(before.name, after) val newParty = Party(before.name, after)
if (before == fixedLeg.fixedRatePayer) { if (before == fixedLeg.fixedRatePayer) {
val deal = copy() val deal = copy()

View File

@ -1,15 +1,7 @@
/*
* Copyright 2015 Distributed Ledger Group LLC. Distributed as Licensed Company IP to DLG Group Members
* pursuant to the August 7, 2015 Advisory Services Agreement and subject to the Company IP License terms
* set forth therein.
*
* All other rights reserved.
*/
package contracts package contracts
fun InterestRateSwap.State.exportIRSToCSV() : String = fun InterestRateSwap.State.exportIRSToCSV(): String =
"Fixed Leg\n" + FixedRatePaymentEvent.CSVHeader + "\n" + "Fixed Leg\n" + FixedRatePaymentEvent.CSVHeader + "\n" +
this.calculation.fixedLegPaymentSchedule.toSortedMap().values.map{ it.asCSV() }.joinToString("\n") + "\n" + this.calculation.fixedLegPaymentSchedule.toSortedMap().values.map { it.asCSV() }.joinToString("\n") + "\n" +
"Floating Leg\n" + FloatingRatePaymentEvent.CSVHeader + "\n" + "Floating Leg\n" + FloatingRatePaymentEvent.CSVHeader + "\n" +
this.calculation.floatingLegPaymentSchedule.toSortedMap().values.map{ it.asCSV() }.joinToString("\n") + "\n" this.calculation.floatingLegPaymentSchedule.toSortedMap().values.map { it.asCSV() }.joinToString("\n") + "\n"

View File

@ -13,7 +13,7 @@ import java.security.PublicKey
open class RatioUnit(value: BigDecimal) { // TODO: Discuss this type open class RatioUnit(value: BigDecimal) { // TODO: Discuss this type
val value = value val value = value
override fun equals(other: Any?): Boolean{ override fun equals(other: Any?): Boolean {
if (this === other) return true if (this === other) return true
if (other?.javaClass != javaClass) return false if (other?.javaClass != javaClass) return false
@ -24,7 +24,7 @@ open class RatioUnit(value: BigDecimal) { // TODO: Discuss this type
return true return true
} }
override fun hashCode(): Int{ override fun hashCode(): Int {
return value.hashCode() return value.hashCode()
} }
@ -34,7 +34,7 @@ open class RatioUnit(value: BigDecimal) { // TODO: Discuss this type
* A class to reprecent a percentage in an unambiguous way. * A class to reprecent a percentage in an unambiguous way.
*/ */
open class PercentageRatioUnit(percentageAsString: String) : RatioUnit(BigDecimal(percentageAsString).divide(BigDecimal("100"))) { open class PercentageRatioUnit(percentageAsString: String) : RatioUnit(BigDecimal(percentageAsString).divide(BigDecimal("100"))) {
override fun toString(): String = value.times(BigDecimal(100)).toString()+"%" override fun toString(): String = value.times(BigDecimal(100)).toString() + "%"
} }
/** /**
@ -45,8 +45,8 @@ open class PercentageRatioUnit(percentageAsString: String) : RatioUnit(BigDecima
val String.percent: PercentageRatioUnit get() = PercentageRatioUnit(this) val String.percent: PercentageRatioUnit get() = PercentageRatioUnit(this)
/** /**
* Interface representing an agreement that exposes various attributes that are common and allow * Interface representing an agreement that exposes various attributes that are common. Implementing it simplifies
* implementation of general protocols that manipulate many agreement types * implementation of general protocols that manipulate many agreement types.
*/ */
interface DealState : LinearState { interface DealState : LinearState {
@ -56,7 +56,7 @@ interface DealState : LinearState {
/** Exposes the Parties involved in a generic way */ /** Exposes the Parties involved in a generic way */
val parties: Array<Party> val parties: Array<Party>
/** Allow swapping in of potentially transaction specific public keys prior to signing */ // TODO: This works by editing the keys used by a Party which is invalid.
fun withPublicKey(before: Party, after: PublicKey): DealState fun withPublicKey(before: Party, after: PublicKey): DealState
/** /**
@ -95,8 +95,7 @@ interface FixableDealState : DealState {
* Parent of the Rate family. Used to denote fixed rates, floating rates, reference rates etc * Parent of the Rate family. Used to denote fixed rates, floating rates, reference rates etc
*/ */
open class Rate(val ratioUnit: RatioUnit? = null) { open class Rate(val ratioUnit: RatioUnit? = null) {
override fun equals(other: Any?): Boolean {
override fun equals(other: Any?): Boolean{
if (this === other) return true if (this === other) return true
if (other?.javaClass != javaClass) return false if (other?.javaClass != javaClass) return false
@ -112,7 +111,7 @@ open class Rate(val ratioUnit: RatioUnit? = null) {
* that have not yet happened. Yet-to-be fixed floating rates need to be equal such that schedules can be tested * that have not yet happened. Yet-to-be fixed floating rates need to be equal such that schedules can be tested
* for equality. * for equality.
*/ */
override fun hashCode(): Int{ override fun hashCode(): Int {
return ratioUnit?.hashCode() ?: 0 return ratioUnit?.hashCode() ?: 0
} }
} }
@ -127,7 +126,7 @@ class FixedRate(ratioUnit: RatioUnit) : Rate(ratioUnit) {
/** /**
* The parent class of the Floating rate classes * The parent class of the Floating rate classes
*/ */
open class FloatingRate: Rate(null) open class FloatingRate : Rate(null)
/** /**
* So a reference rate is a rate that takes its value from a source at a given date * So a reference rate is a rate that takes its value from a source at a given date

View File

@ -1,17 +1,10 @@
/*
* Copyright 2015 Distributed Ledger Group LLC. Distributed as Licensed Company IP to DLG Group Members
* pursuant to the August 7, 2015 Advisory Services Agreement and subject to the Company IP License terms
* set forth therein.
*
* All other rights reserved.
*/
package core.crypto; package core.crypto;
public class AddressFormatException extends IllegalArgumentException { public class AddressFormatException extends IllegalArgumentException {
public AddressFormatException() { public AddressFormatException() {
super(); super();
} }
public AddressFormatException(String message) { public AddressFormatException(String message) {
super(message); super(message);
} }

View File

@ -1,11 +1,3 @@
/*
* Copyright 2015 Distributed Ledger Group LLC. Distributed as Licensed Company IP to DLG Group Members
* pursuant to the August 7, 2015 Advisory Services Agreement and subject to the Company IP License terms
* set forth therein.
*
* All other rights reserved.
*/
package core.crypto; package core.crypto;
import java.math.*; import java.math.*;
@ -31,7 +23,7 @@ import java.util.*;
* base-256 digits, convert the number to be represented using base-58 digits, preserve the exact * base-256 digits, convert the number to be represented using base-58 digits, preserve the exact
* number of leading zeros (which are otherwise lost during the mathematical operations on the * number of leading zeros (which are otherwise lost during the mathematical operations on the
* numbers), and finally represent the resulting base-58 digits as alphanumeric ASCII characters. * numbers), and finally represent the resulting base-58 digits as alphanumeric ASCII characters.
* * <p>
* NB: This class originally comes from the Apache licensed bitcoinj library. The original author of this code is the * NB: This class originally comes from the Apache licensed bitcoinj library. The original author of this code is the
* same as the original author of the R3 repository. * same as the original author of the R3 repository.
*/ */
@ -39,6 +31,7 @@ public class Base58 {
public static final char[] ALPHABET = "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz".toCharArray(); public static final char[] ALPHABET = "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz".toCharArray();
private static final char ENCODED_ZERO = ALPHABET[0]; private static final char ENCODED_ZERO = ALPHABET[0];
private static final int[] INDEXES = new int[128]; private static final int[] INDEXES = new int[128];
static { static {
Arrays.fill(INDEXES, -1); Arrays.fill(INDEXES, -1);
for (int i = 0; i < ALPHABET.length; i++) { for (int i = 0; i < ALPHABET.length; i++) {

View File

@ -1,11 +1,3 @@
/*
* Copyright 2015 Distributed Ledger Group LLC. Distributed as Licensed Company IP to DLG Group Members
* pursuant to the August 7, 2015 Advisory Services Agreement and subject to the Company IP License terms
* set forth therein.
*
* All other rights reserved.
*/
package core package core
import java.security.PublicKey import java.security.PublicKey
@ -43,6 +35,7 @@ class Requirements {
if (!expr) throw IllegalArgumentException("Failed requirement: $this") if (!expr) throw IllegalArgumentException("Failed requirement: $this")
} }
} }
val R = Requirements() val R = Requirements()
inline fun <R> requireThat(body: Requirements.() -> R) = R.body() inline fun <R> requireThat(body: Requirements.() -> R) = R.body()

View File

@ -1,11 +1,3 @@
/*
* Copyright 2015 Distributed Ledger Group LLC. Distributed as Licensed Company IP to DLG Group Members
* pursuant to the August 7, 2015 Advisory Services Agreement and subject to the Company IP License terms
* set forth therein.
*
* All other rights reserved.
*/
package core package core
import com.fasterxml.jackson.core.JsonGenerator import com.fasterxml.jackson.core.JsonGenerator
@ -46,7 +38,7 @@ data class Amount(val pennies: Long, val currency: Currency) : Comparable<Amount
require(pennies >= 0) { "Negative amounts are not allowed: $pennies" } require(pennies >= 0) { "Negative amounts are not allowed: $pennies" }
} }
constructor(amount:BigDecimal, currency: Currency) : this(amount.toLong(), currency) constructor(amount: BigDecimal, currency: Currency) : this(amount.toLong(), currency)
operator fun plus(other: Amount): Amount { operator fun plus(other: Amount): Amount {
checkCurrency(other) checkCurrency(other)
@ -87,6 +79,7 @@ fun Iterable<Amount>.sumOrZero(currency: Currency) = if (iterator().hasNext()) s
/** A [FixOf] identifies the question side of a fix: what day, tenor and type of fix ("LIBOR", "EURIBOR" etc) */ /** A [FixOf] identifies the question side of a fix: what day, tenor and type of fix ("LIBOR", "EURIBOR" etc) */
data class FixOf(val name: String, val forDay: LocalDate, val ofTenor: Tenor) data class FixOf(val name: String, val forDay: LocalDate, val ofTenor: Tenor)
/** A [Fix] represents a named interest rate, on a given day, for a given duration. It can be embedded in a tx. */ /** A [Fix] represents a named interest rate, on a given day, for a given duration. It can be embedded in a tx. */
data class Fix(val of: FixOf, val value: BigDecimal) : CommandData data class Fix(val of: FixOf, val value: BigDecimal) : CommandData
@ -98,13 +91,13 @@ data class Fix(val of: FixOf, val value: BigDecimal) : CommandData
@JsonSerialize(using = ExpressionSerializer::class) @JsonSerialize(using = ExpressionSerializer::class)
data class Expression(val expr: String) data class Expression(val expr: String)
object ExpressionSerializer: JsonSerializer<Expression>() { object ExpressionSerializer : JsonSerializer<Expression>() {
override fun serialize(expr: Expression, generator: JsonGenerator, provider: SerializerProvider) { override fun serialize(expr: Expression, generator: JsonGenerator, provider: SerializerProvider) {
generator.writeString(expr.expr) generator.writeString(expr.expr)
} }
} }
object ExpressionDeserializer: JsonDeserializer<Expression>() { object ExpressionDeserializer : JsonDeserializer<Expression>() {
override fun deserialize(parser: JsonParser, context: DeserializationContext): Expression { override fun deserialize(parser: JsonParser, context: DeserializationContext): Expression {
return Expression(parser.text) return Expression(parser.text)
} }
@ -112,13 +105,14 @@ object ExpressionDeserializer: JsonDeserializer<Expression>() {
/** /**
* Placeholder class for the Tenor datatype - which is a standardised duration of time until maturity */ * Placeholder class for the Tenor datatype - which is a standardised duration of time until maturity */
data class Tenor(val name:String) { data class Tenor(val name: String) {
init { init {
val verifier = Regex("([0-9])+([DMYW])") // Only doing Overnight, Day, Week, Month, Year for now. val verifier = Regex("([0-9])+([DMYW])") // Only doing Overnight, Day, Week, Month, Year for now.
if (!(name == "ON" || verifier.containsMatchIn(name))) { if (!(name == "ON" || verifier.containsMatchIn(name))) {
throw IllegalArgumentException("Unrecognized tenor : $name") throw IllegalArgumentException("Unrecognized tenor : $name")
} }
} }
override fun toString(): String = "$name" override fun toString(): String = "$name"
} }
@ -126,7 +120,7 @@ data class Tenor(val name:String) {
* We don't actually do anything with this yet though, so it's ignored for now. * We don't actually do anything with this yet though, so it's ignored for now.
*/ */
enum class AccrualAdjustment { enum class AccrualAdjustment {
Adjusted,Unadjusted Adjusted, Unadjusted
} }
/** This is utilised in the [DateRollConvention] class to determine which way we should initially step when /** This is utilised in the [DateRollConvention] class to determine which way we should initially step when
@ -184,7 +178,9 @@ enum class DateRollConvention {
* in the toString lest some people get confused. */ * in the toString lest some people get confused. */
enum class DayCountBasisDay { enum class DayCountBasisDay {
// We have to prefix 30 etc with a letter due to enum naming constraints. // We have to prefix 30 etc with a letter due to enum naming constraints.
D30, D30N, D30P, D30E, D30G, DActual, DActualJ, D30Z, D30F, DBus_SaoPaulo; D30,
D30N, D30P, D30E, D30G, DActual, DActualJ, D30Z, D30F, DBus_SaoPaulo;
override fun toString(): String { override fun toString(): String {
return super.toString().drop(1) return super.toString().drop(1)
} }
@ -193,7 +189,9 @@ enum class DayCountBasisDay {
/** This forms the year part of the "Day Count Basis" used for interest calculation. */ /** This forms the year part of the "Day Count Basis" used for interest calculation. */
enum class DayCountBasisYear { enum class DayCountBasisYear {
// Ditto above comment for years. // Ditto above comment for years.
Y360, Y365F, Y365L, Y365Q, Y366, YActual, YActualA, Y365B, Y365, YISMA, YICMA, Y252; Y360,
Y365F, Y365L, Y365Q, Y366, YActual, YActualA, Y365B, Y365, YISMA, YICMA, Y252;
override fun toString(): String { override fun toString(): String {
return super.toString().drop(1) return super.toString().drop(1)
} }
@ -210,7 +208,8 @@ enum class PaymentRule {
*/ */
enum class DateOffset { enum class DateOffset {
// TODO: Definitely shouldn't be an enum, but let's leave it for now at T-2 is a convention. // TODO: Definitely shouldn't be an enum, but let's leave it for now at T-2 is a convention.
ZERO, TWODAYS, ZERO,
TWODAYS,
} }
@ -237,6 +236,7 @@ enum class Frequency(val annualCompoundCount: Int) {
BiWeekly(26) { BiWeekly(26) {
override fun offset(d: LocalDate) = d.plusWeeks(2) override fun offset(d: LocalDate) = d.plusWeeks(2)
}; };
abstract fun offset(d: LocalDate): LocalDate abstract fun offset(d: LocalDate): LocalDate
// Daily() // Let's not worry about this for now. // Daily() // Let's not worry about this for now.
} }
@ -252,10 +252,10 @@ fun LocalDate.isWorkingDay(accordingToCalendar: BusinessCalendar): Boolean = acc
* no staff are around to handle problems. * no staff are around to handle problems.
*/ */
open class BusinessCalendar private constructor(val calendars: Array<out String>, val holidayDates: List<LocalDate>) { open class BusinessCalendar private constructor(val calendars: Array<out String>, val holidayDates: List<LocalDate>) {
class UnknownCalendar(name: String): Exception("$name not found") class UnknownCalendar(name: String) : Exception("$name not found")
companion object { companion object {
val calendars = listOf("London","NewYork") val calendars = listOf("London", "NewYork")
val TEST_CALENDAR_DATA = calendars.map { val TEST_CALENDAR_DATA = calendars.map {
it to BusinessCalendar::class.java.getResourceAsStream("${it}HolidayCalendar.txt").bufferedReader().readText() it to BusinessCalendar::class.java.getResourceAsStream("${it}HolidayCalendar.txt").bufferedReader().readText()
@ -268,7 +268,7 @@ open class BusinessCalendar private constructor(val calendars: Array<out String>
fun getInstance(vararg calname: String) = BusinessCalendar(calname, fun getInstance(vararg calname: String) = BusinessCalendar(calname,
calname.flatMap { (TEST_CALENDAR_DATA[it] ?: throw UnknownCalendar(it)).split(",") }. calname.flatMap { (TEST_CALENDAR_DATA[it] ?: throw UnknownCalendar(it)).split(",") }.
toSet(). toSet().
map{ parseDateFromString(it) }. map { parseDateFromString(it) }.
toList().sorted() toList().sorted()
) )

View File

@ -1,11 +1,3 @@
/*
* Copyright 2015 Distributed Ledger Group LLC. Distributed as Licensed Company IP to DLG Group Members
* pursuant to the August 7, 2015 Advisory Services Agreement and subject to the Company IP License terms
* set forth therein.
*
* All other rights reserved.
*/
package core package core
import core.crypto.SecureHash import core.crypto.SecureHash
@ -18,7 +10,6 @@ import java.io.OutputStream
import java.security.PublicKey import java.security.PublicKey
import java.time.Duration import java.time.Duration
import java.time.Instant import java.time.Instant
import java.time.LocalDate
import java.util.jar.JarInputStream import java.util.jar.JarInputStream
/** Implemented by anything that can be named by a secure hash value (e.g. transactions, attachments). */ /** Implemented by anything that can be named by a secure hash value (e.g. transactions, attachments). */
@ -51,7 +42,7 @@ interface OwnableState : ContractState {
* *
* This simplifies the job of tracking the current version of certain types of state in e.g. a wallet * This simplifies the job of tracking the current version of certain types of state in e.g. a wallet
*/ */
interface LinearState: ContractState { interface LinearState : ContractState {
/** Unique thread id within the wallets of all parties */ /** Unique thread id within the wallets of all parties */
val thread: SecureHash val thread: SecureHash
@ -73,6 +64,11 @@ data class StateRef(val txhash: SecureHash, val index: Int) {
/** A StateAndRef is simply a (state, ref) pair. For instance, a wallet (which holds available assets) contains these. */ /** A StateAndRef is simply a (state, ref) pair. For instance, a wallet (which holds available assets) contains these. */
data class StateAndRef<out T : ContractState>(val state: T, val ref: StateRef) data class StateAndRef<out T : ContractState>(val state: T, val ref: StateRef)
/** Filters a list of [StateAndRef] objects according to the type of the states */
inline fun <reified T : ContractState> List<StateAndRef<ContractState>>.filterStatesOfType(): List<StateAndRef<T>> {
return mapNotNull { if (it.state is T) StateAndRef(it.state, it.ref) else null }
}
/** A [Party] is well known (name, pubkey) pair. In a real system this would probably be an X.509 certificate. */ /** A [Party] is well known (name, pubkey) pair. In a real system this would probably be an X.509 certificate. */
data class Party(val name: String, val owningKey: PublicKey) { data class Party(val name: String, val owningKey: PublicKey) {
override fun toString() = name override fun toString() = name
@ -103,6 +99,7 @@ data class Command(val data: CommandData, val pubkeys: List<PublicKey>) {
init { init {
require(pubkeys.isNotEmpty()) require(pubkeys.isNotEmpty())
} }
constructor(data: CommandData, key: PublicKey) : this(data, listOf(key)) constructor(data: CommandData, key: PublicKey) : this(data, listOf(key))
private fun commandDataToString() = data.toString().let { if (it.contains("@")) it.replace('$', '.').split("@")[0] else it } private fun commandDataToString() = data.toString().let { if (it.contains("@")) it.replace('$', '.').split("@")[0] else it }

View File

@ -1,11 +1,3 @@
/*
* Copyright 2015 Distributed Ledger Group LLC. Distributed as Licensed Company IP to DLG Group Members
* pursuant to the August 7, 2015 Advisory Services Agreement and subject to the Company IP License terms
* set forth therein.
*
* All other rights reserved.
*/
package core package core
import core.crypto.SecureHash import core.crypto.SecureHash

View File

@ -1,11 +1,3 @@
/*
* Copyright 2015 Distributed Ledger Group LLC. Distributed as Licensed Company IP to DLG Group Members
* pursuant to the August 7, 2015 Advisory Services Agreement and subject to the Company IP License terms
* set forth therein.
*
* All other rights reserved.
*/
package core package core
import core.crypto.SecureHash import core.crypto.SecureHash

View File

@ -1,11 +1,3 @@
/*
* Copyright 2015 Distributed Ledger Group LLC. Distributed as Licensed Company IP to DLG Group Members
* pursuant to the August 7, 2015 Advisory Services Agreement and subject to the Company IP License terms
* set forth therein.
*
* All other rights reserved.
*/
package core package core
import co.paralleluniverse.fibers.Suspendable import co.paralleluniverse.fibers.Suspendable
@ -106,7 +98,9 @@ data class WireTransaction(val inputs: List<StateRef>,
/** Container for a [WireTransaction] and attached signatures. */ /** Container for a [WireTransaction] and attached signatures. */
data class SignedTransaction(val txBits: SerializedBytes<WireTransaction>, data class SignedTransaction(val txBits: SerializedBytes<WireTransaction>,
val sigs: List<DigitalSignature.WithKey>) : NamedByHash { val sigs: List<DigitalSignature.WithKey>) : NamedByHash {
init { check(sigs.isNotEmpty()) } init {
check(sigs.isNotEmpty())
}
/** Lazily calculated access to the deserialised/hashed transaction data. */ /** Lazily calculated access to the deserialised/hashed transaction data. */
val tx: WireTransaction by lazy { WireTransaction.deserialize(txBits) } val tx: WireTransaction by lazy { WireTransaction.deserialize(txBits) }
@ -300,6 +294,7 @@ class TransactionBuilder(private val inputs: MutableList<StateRef> = arrayListOf
// Accessors that yield immutable snapshots. // Accessors that yield immutable snapshots.
fun inputStates(): List<StateRef> = ArrayList(inputs) fun inputStates(): List<StateRef> = ArrayList(inputs)
fun outputStates(): List<ContractState> = ArrayList(outputs) fun outputStates(): List<ContractState> = ArrayList(outputs)
fun commands(): List<Command> = ArrayList(commands) fun commands(): List<Command> = ArrayList(commands)
fun attachments(): List<SecureHash> = ArrayList(attachments) fun attachments(): List<SecureHash> = ArrayList(attachments)

View File

@ -1,11 +1,3 @@
/*
* Copyright 2015 Distributed Ledger Group LLC. Distributed as Licensed Company IP to DLG Group Members
* pursuant to the August 7, 2015 Advisory Services Agreement and subject to the Company IP License terms
* set forth therein.
*
* All other rights reserved.
*/
package core package core
import com.google.common.io.ByteStreams import com.google.common.io.ByteStreams
@ -46,13 +38,24 @@ fun random63BitValue(): Long = Math.abs(SecureRandom.getInstanceStrong().nextLon
// Some utilities for working with Guava listenable futures. // Some utilities for working with Guava listenable futures.
fun <T> ListenableFuture<T>.then(executor: Executor, body: () -> Unit) = addListener(Runnable(body), executor) fun <T> ListenableFuture<T>.then(executor: Executor, body: () -> Unit) = addListener(Runnable(body), executor)
fun <T> ListenableFuture<T>.success(executor: Executor, body: (T) -> Unit) = then(executor) { fun <T> ListenableFuture<T>.success(executor: Executor, body: (T) -> Unit) = then(executor) {
val r = try { get() } catch(e: Throwable) { return@then } val r = try {
get()
} catch(e: Throwable) {
return@then
}
body(r) body(r)
} }
fun <T> ListenableFuture<T>.failure(executor: Executor, body: (Throwable) -> Unit) = then(executor) { fun <T> ListenableFuture<T>.failure(executor: Executor, body: (Throwable) -> Unit) = then(executor) {
try { get() } catch(e: Throwable) { body(e) } try {
get()
} catch(e: Throwable) {
body(e)
}
} }
infix fun <T> ListenableFuture<T>.then(body: () -> Unit): ListenableFuture<T> = apply { then(RunOnCallerThread, body) } infix fun <T> ListenableFuture<T>.then(body: () -> Unit): ListenableFuture<T> = apply { then(RunOnCallerThread, body) }
infix fun <T> ListenableFuture<T>.success(body: (T) -> Unit): ListenableFuture<T> = apply { success(RunOnCallerThread, body) } infix fun <T> ListenableFuture<T>.success(body: (T) -> Unit): ListenableFuture<T> = apply { success(RunOnCallerThread, body) }
infix fun <T> ListenableFuture<T>.failure(body: (Throwable) -> Unit): ListenableFuture<T> = apply { failure(RunOnCallerThread, body) } infix fun <T> ListenableFuture<T>.failure(body: (Throwable) -> Unit): ListenableFuture<T> = apply { failure(RunOnCallerThread, body) }

View File

@ -1,11 +1,3 @@
/*
* Copyright 2015 Distributed Ledger Group LLC. Distributed as Licensed Company IP to DLG Group Members
* pursuant to the August 7, 2015 Advisory Services Agreement and subject to the Company IP License terms
* set forth therein.
*
* All other rights reserved.
*/
package core.crypto package core.crypto
import com.google.common.io.BaseEncoding import com.google.common.io.BaseEncoding
@ -18,7 +10,10 @@ import java.security.interfaces.ECPublicKey
// "sealed" here means there can't be any subclasses other than the ones defined here. // "sealed" here means there can't be any subclasses other than the ones defined here.
sealed class SecureHash private constructor(bits: ByteArray) : OpaqueBytes(bits) { sealed class SecureHash private constructor(bits: ByteArray) : OpaqueBytes(bits) {
class SHA256(bits: ByteArray) : SecureHash(bits) { class SHA256(bits: ByteArray) : SecureHash(bits) {
init { require(bits.size == 32) } init {
require(bits.size == 32)
}
override val signatureAlgorithmName: String get() = "SHA256withECDSA" override val signatureAlgorithmName: String get() = "SHA256withECDSA"
} }
@ -97,6 +92,7 @@ fun PrivateKey.signWithECDSA(bits: ByteArray): DigitalSignature {
fun PrivateKey.signWithECDSA(bitsToSign: ByteArray, publicKey: PublicKey): DigitalSignature.WithKey { fun PrivateKey.signWithECDSA(bitsToSign: ByteArray, publicKey: PublicKey): DigitalSignature.WithKey {
return DigitalSignature.WithKey(publicKey, signWithECDSA(bitsToSign).bits) return DigitalSignature.WithKey(publicKey, signWithECDSA(bitsToSign).bits)
} }
fun KeyPair.signWithECDSA(bitsToSign: ByteArray) = private.signWithECDSA(bitsToSign, public) fun KeyPair.signWithECDSA(bitsToSign: ByteArray) = private.signWithECDSA(bitsToSign, public)
fun KeyPair.signWithECDSA(bitsToSign: OpaqueBytes) = private.signWithECDSA(bitsToSign.bits, public) fun KeyPair.signWithECDSA(bitsToSign: OpaqueBytes) = private.signWithECDSA(bitsToSign.bits, public)
fun KeyPair.signWithECDSA(bitsToSign: OpaqueBytes, party: Party) = signWithECDSA(bitsToSign.bits, party) fun KeyPair.signWithECDSA(bitsToSign: OpaqueBytes, party: Party) = signWithECDSA(bitsToSign.bits, party)
@ -124,6 +120,7 @@ fun PublicKey.toStringShort(): String {
// Allow Kotlin destructuring: val (private, public) = keypair // Allow Kotlin destructuring: val (private, public) = keypair
operator fun KeyPair.component1() = this.private operator fun KeyPair.component1() = this.private
operator fun KeyPair.component2() = this.public operator fun KeyPair.component2() = this.public
/** A simple wrapper that will make it easier to swap out the EC algorithm we use in future */ /** A simple wrapper that will make it easier to swap out the EC algorithm we use in future */

View File

@ -43,7 +43,7 @@ class CubicSplineInterpolator(private val xs: DoubleArray, private val ys: Doubl
val z = DoubleArray(n) val z = DoubleArray(n)
for (i in 1..n - 1) { for (i in 1..n - 1) {
val l = 2 * (xs[i + 1] - xs[i - 1]) - h[i - 1] * m[i - 1] val l = 2 * (xs[i + 1] - xs[i - 1]) - h[i - 1] * m[i - 1]
m[i] = h[i]/l m[i] = h[i] / l
z[i] = (g[i] - h[i - 1] * z[i - 1]) / l z[i] = (g[i] - h[i - 1] * z[i - 1]) / l
} }
for (j in n - 1 downTo 0) { for (j in n - 1 downTo 0) {

View File

@ -1,11 +1,3 @@
/*
* Copyright 2015 Distributed Ledger Group LLC. Distributed as Licensed Company IP to DLG Group Members
* pursuant to the August 7, 2015 Advisory Services Agreement and subject to the Company IP License terms
* set forth therein.
*
* All other rights reserved.
*/
package core.node.services package core.node.services
import core.Party import core.Party

View File

@ -1,11 +1,3 @@
/*
* Copyright 2015 Distributed Ledger Group LLC. Distributed as Licensed Company IP to DLG Group Members
* pursuant to the August 7, 2015 Advisory Services Agreement and subject to the Company IP License terms
* set forth therein.
*
* All other rights reserved.
*/
package core.node.services package core.node.services
import co.paralleluniverse.fibers.Suspendable import co.paralleluniverse.fibers.Suspendable

View File

@ -1,11 +1,3 @@
/*
* Copyright 2015 Distributed Ledger Group LLC. Distributed as Licensed Company IP to DLG Group Members
* pursuant to the August 7, 2015 Advisory Services Agreement and subject to the Company IP License terms
* set forth therein.
*
* All other rights reserved.
*/
package core.serialization package core.serialization
import com.google.common.io.BaseEncoding import com.google.common.io.BaseEncoding
@ -17,13 +9,15 @@ import java.util.*
* functionality to Java, but it won't arrive for a few years yet! * functionality to Java, but it won't arrive for a few years yet!
*/ */
open class OpaqueBytes(val bits: ByteArray) { open class OpaqueBytes(val bits: ByteArray) {
init { check(bits.isNotEmpty()) } init {
check(bits.isNotEmpty())
}
companion object { companion object {
fun of(vararg b: Byte) = OpaqueBytes(byteArrayOf(*b)) fun of(vararg b: Byte) = OpaqueBytes(byteArrayOf(*b))
} }
override fun equals(other: Any?): Boolean{ override fun equals(other: Any?): Boolean {
if (this === other) return true if (this === other) return true
if (other !is OpaqueBytes) return false if (other !is OpaqueBytes) return false
return Arrays.equals(bits, other.bits) return Arrays.equals(bits, other.bits)

View File

@ -1,11 +1,3 @@
/*
* Copyright 2015 Distributed Ledger Group LLC. Distributed as Licensed Company IP to DLG Group Members
* pursuant to the August 7, 2015 Advisory Services Agreement and subject to the Company IP License terms
* set forth therein.
*
* All other rights reserved.
*/
package core.serialization package core.serialization
import co.paralleluniverse.fibers.Fiber import co.paralleluniverse.fibers.Fiber
@ -81,12 +73,15 @@ inline fun <reified T : Any> ByteArray.deserialize(kryo: Kryo = THREAD_LOCAL_KRY
else else
return kryo.readObject(Input(this), T::class.java) return kryo.readObject(Input(this), T::class.java)
} }
inline fun <reified T : Any> OpaqueBytes.deserialize(kryo: Kryo = THREAD_LOCAL_KRYO.get(), includeClassName: Boolean = false): T { inline fun <reified T : Any> OpaqueBytes.deserialize(kryo: Kryo = THREAD_LOCAL_KRYO.get(), includeClassName: Boolean = false): T {
return this.bits.deserialize(kryo, includeClassName) return this.bits.deserialize(kryo, includeClassName)
} }
// The more specific deserialize version results in the bytes being cached, which is faster. // The more specific deserialize version results in the bytes being cached, which is faster.
@JvmName("SerializedBytesWireTransaction") @JvmName("SerializedBytesWireTransaction")
fun SerializedBytes<WireTransaction>.deserialize(kryo: Kryo = THREAD_LOCAL_KRYO.get()): WireTransaction = WireTransaction.deserialize(this, kryo) fun SerializedBytes<WireTransaction>.deserialize(kryo: Kryo = THREAD_LOCAL_KRYO.get()): WireTransaction = WireTransaction.deserialize(this, kryo)
inline fun <reified T : Any> SerializedBytes<T>.deserialize(kryo: Kryo = THREAD_LOCAL_KRYO.get(), includeClassName: Boolean = false): T = bits.deserialize(kryo, includeClassName) inline fun <reified T : Any> SerializedBytes<T>.deserialize(kryo: Kryo = THREAD_LOCAL_KRYO.get(), includeClassName: Boolean = false): T = bits.deserialize(kryo, includeClassName)
/** /**
@ -175,7 +170,11 @@ class ImmutableClassSerializer<T : Any>(val klass: KClass<T>) : Serializer<T>()
} }
} }
// If the constructor throws an exception, pass it through instead of wrapping it. // If the constructor throws an exception, pass it through instead of wrapping it.
return try { constructor.call(*args) } catch (e: InvocationTargetException) { throw e.cause!! } return try {
constructor.call(*args)
} catch (e: InvocationTargetException) {
throw e.cause!!
}
} }
} }
@ -198,7 +197,7 @@ fun createKryo(k: Kryo = Kryo()): Kryo {
// no-arg constructor available. // no-arg constructor available.
instantiatorStrategy = Kryo.DefaultInstantiatorStrategy(StdInstantiatorStrategy()) instantiatorStrategy = Kryo.DefaultInstantiatorStrategy(StdInstantiatorStrategy())
register(Arrays.asList( "" ).javaClass, ArraysAsListSerializer()); register(Arrays.asList("").javaClass, ArraysAsListSerializer());
// Because we like to stick a Kryo object in a ThreadLocal to speed things up a bit, we can end up trying to // Because we like to stick a Kryo object in a ThreadLocal to speed things up a bit, we can end up trying to
// serialise the Kryo object itself when suspending a fiber. That's dumb, useless AND can cause crashes, so // serialise the Kryo object itself when suspending a fiber. That's dumb, useless AND can cause crashes, so

View File

@ -1,11 +1,3 @@
/*
* Copyright 2015 Distributed Ledger Group LLC. Distributed as Licensed Company IP to DLG Group Members
* pursuant to the August 7, 2015 Advisory Services Agreement and subject to the Company IP License terms
* set forth therein.
*
* All other rights reserved.
*/
package core.utilities package core.utilities
/** /**

View File

@ -1,11 +1,3 @@
/*
* Copyright 2015 Distributed Ledger Group LLC. Distributed as Licensed Company IP to DLG Group Members
* pursuant to the August 7, 2015 Advisory Services Agreement and subject to the Company IP License terms
* set forth therein.
*
* All other rights reserved.
*/
package core.utilities package core.utilities
import core.TransientProperty import core.TransientProperty
@ -45,9 +37,11 @@ class ProgressTracker(vararg steps: Step) {
class Position(val tracker: ProgressTracker, val newStep: Step) : Change() { class Position(val tracker: ProgressTracker, val newStep: Step) : Change() {
override fun toString() = newStep.label override fun toString() = newStep.label
} }
class Rendering(val tracker: ProgressTracker, val ofStep: Step) : Change() { class Rendering(val tracker: ProgressTracker, val ofStep: Step) : Change() {
override fun toString() = ofStep.label override fun toString() = ofStep.label
} }
class Structural(val tracker: ProgressTracker, val parent: Step) : Change() { class Structural(val tracker: ProgressTracker, val parent: Step) : Change() {
override fun toString() = "Structural step change in child of ${parent.label}" override fun toString() = "Structural step change in child of ${parent.label}"
} }
@ -75,6 +69,7 @@ class ProgressTracker(vararg steps: Step) {
object UNSTARTED : Step("Unstarted") { object UNSTARTED : Step("Unstarted") {
override fun equals(other: Any?) = other is UNSTARTED override fun equals(other: Any?) = other is UNSTARTED
} }
object DONE : Step("Done") { object DONE : Step("Done") {
override fun equals(other: Any?) = other is DONE override fun equals(other: Any?) = other is DONE
} }

View File

@ -1,11 +1,3 @@
/*
* Copyright 2015 Distributed Ledger Group LLC. Distributed as Licensed Company IP to DLG Group Members
* pursuant to the August 7, 2015 Advisory Services Agreement and subject to the Company IP License terms
* set forth therein.
*
* All other rights reserved.
*/
package core package core
import org.junit.Test import org.junit.Test
@ -40,7 +32,7 @@ class FinanceTypesTest {
fun `schedule generator 1`() { fun `schedule generator 1`() {
var ret = BusinessCalendar.createGenericSchedule(startDate = LocalDate.of(2014, 11, 25), period = Frequency.Monthly, noOfAdditionalPeriods = 3) var ret = BusinessCalendar.createGenericSchedule(startDate = LocalDate.of(2014, 11, 25), period = Frequency.Monthly, noOfAdditionalPeriods = 3)
// We know that Jan 25th 2015 is on the weekend -> It should not be in this list returned. // We know that Jan 25th 2015 is on the weekend -> It should not be in this list returned.
assert(! (LocalDate.of(2015,1,25) in ret)) assert(!(LocalDate.of(2015, 1, 25) in ret))
println(ret) println(ret)
} }
@ -48,61 +40,61 @@ class FinanceTypesTest {
fun `schedule generator 2`() { fun `schedule generator 2`() {
var ret = BusinessCalendar.createGenericSchedule(startDate = LocalDate.of(2015, 11, 25), period = Frequency.Monthly, noOfAdditionalPeriods = 3, calendar = BusinessCalendar.getInstance("London"), dateRollConvention = DateRollConvention.Following) var ret = BusinessCalendar.createGenericSchedule(startDate = LocalDate.of(2015, 11, 25), period = Frequency.Monthly, noOfAdditionalPeriods = 3, calendar = BusinessCalendar.getInstance("London"), dateRollConvention = DateRollConvention.Following)
// Xmas should not be in the list! // Xmas should not be in the list!
assert(! (LocalDate.of(2015,12,25) in ret)) assert(!(LocalDate.of(2015, 12, 25) in ret))
println(ret) println(ret)
} }
@Test @Test
fun `create a UK calendar` () { fun `create a UK calendar`() {
val cal = BusinessCalendar.getInstance("London") val cal = BusinessCalendar.getInstance("London")
val holdates = cal.holidayDates val holdates = cal.holidayDates
println(holdates) println(holdates)
assert(LocalDate.of(2016,12,27) in holdates) // Christmas this year is at the weekend... assert(LocalDate.of(2016, 12, 27) in holdates) // Christmas this year is at the weekend...
} }
@Test @Test
fun `create a US UK calendar`() { fun `create a US UK calendar`() {
val cal = BusinessCalendar.getInstance("London","NewYork") val cal = BusinessCalendar.getInstance("London", "NewYork")
assert(LocalDate.of(2016,7,4) in cal.holidayDates) // The most American of holidays assert(LocalDate.of(2016, 7, 4) in cal.holidayDates) // The most American of holidays
assert(LocalDate.of(2016,8,29) in cal.holidayDates) // August Bank Holiday for brits only assert(LocalDate.of(2016, 8, 29) in cal.holidayDates) // August Bank Holiday for brits only
println("Calendar contains both US and UK holidays") println("Calendar contains both US and UK holidays")
} }
@Test @Test
fun `calendar test of modified following` () { fun `calendar test of modified following`() {
val ldn = BusinessCalendar.getInstance("London") val ldn = BusinessCalendar.getInstance("London")
val result = ldn.applyRollConvention(LocalDate.of(2016,12,25),DateRollConvention.ModifiedFollowing) val result = ldn.applyRollConvention(LocalDate.of(2016, 12, 25), DateRollConvention.ModifiedFollowing)
assert(result == LocalDate.of(2016,12,28)) assert(result == LocalDate.of(2016, 12, 28))
} }
@Test @Test
fun `calendar test of modified following pt 2` () { fun `calendar test of modified following pt 2`() {
val ldn = BusinessCalendar.getInstance("London") val ldn = BusinessCalendar.getInstance("London")
val result = ldn.applyRollConvention(LocalDate.of(2016,12,31),DateRollConvention.ModifiedFollowing) val result = ldn.applyRollConvention(LocalDate.of(2016, 12, 31), DateRollConvention.ModifiedFollowing)
assert(result == LocalDate.of(2016,12,30)) assert(result == LocalDate.of(2016, 12, 30))
} }
@Test @Test
fun `calendar test of modified previous` () { fun `calendar test of modified previous`() {
val ldn = BusinessCalendar.getInstance("London") val ldn = BusinessCalendar.getInstance("London")
val result = ldn.applyRollConvention(LocalDate.of(2016,1,1),DateRollConvention.ModifiedPrevious) val result = ldn.applyRollConvention(LocalDate.of(2016, 1, 1), DateRollConvention.ModifiedPrevious)
assert(result == LocalDate.of(2016,1,4)) assert(result == LocalDate.of(2016, 1, 4))
} }
@Test @Test
fun `calendar test of previous` () { fun `calendar test of previous`() {
val ldn = BusinessCalendar.getInstance("London") val ldn = BusinessCalendar.getInstance("London")
val result = ldn.applyRollConvention(LocalDate.of(2016,12,25),DateRollConvention.Previous) val result = ldn.applyRollConvention(LocalDate.of(2016, 12, 25), DateRollConvention.Previous)
assert(result == LocalDate.of(2016,12,23)) assert(result == LocalDate.of(2016, 12, 23))
} }
@Test @Test
fun `calendar test of following` () { fun `calendar test of following`() {
val ldn = BusinessCalendar.getInstance("London") val ldn = BusinessCalendar.getInstance("London")
val result = ldn.applyRollConvention(LocalDate.of(2016,12,25),DateRollConvention.Following) val result = ldn.applyRollConvention(LocalDate.of(2016, 12, 25), DateRollConvention.Following)
assert(result == LocalDate.of(2016,12,28)) assert(result == LocalDate.of(2016, 12, 28))
} }
@Test @Test
@ -147,5 +139,4 @@ class FinanceTypesTest {
} }
} }

View File

@ -1,11 +1,3 @@
/*
* Copyright 2015 Distributed Ledger Group LLC. Distributed as Licensed Company IP to DLG Group Members
* pursuant to the August 7, 2015 Advisory Services Agreement and subject to the Company IP License terms
* set forth therein.
*
* All other rights reserved.
*/
package core.utilities package core.utilities
import org.apache.commons.jexl3.JexlBuilder import org.apache.commons.jexl3.JexlBuilder

View File

@ -1,11 +1,3 @@
/*
* Copyright 2015 Distributed Ledger Group LLC. Distributed as Licensed Company IP to DLG Group Members
* pursuant to the August 7, 2015 Advisory Services Agreement and subject to the Company IP License terms
* set forth therein.
*
* All other rights reserved.
*/
package core.utilities package core.utilities
import org.junit.Before import org.junit.Before

View File

@ -1,11 +1,3 @@
/*
* Copyright 2016 Distributed Ledger Group LLC. Distributed as Licensed Company IP to DLG Group Members
* pursuant to the August 7, 2015 Advisory Services Agreement and subject to the Company IP License terms
* set forth therein.
*
* All other rights reserved.
*/
package api package api
import core.ContractState import core.ContractState

View File

@ -2,10 +2,14 @@ package api
import com.google.common.util.concurrent.ListenableFuture import com.google.common.util.concurrent.ListenableFuture
import contracts.DealState import contracts.DealState
import core.* import core.ContractState
import core.SignedTransaction
import core.StateRef
import core.WireTransaction
import core.crypto.DigitalSignature import core.crypto.DigitalSignature
import core.crypto.SecureHash import core.crypto.SecureHash
import core.node.AbstractNode import core.node.AbstractNode
import core.node.services.linearHeadsOfType
import core.protocols.ProtocolLogic import core.protocols.ProtocolLogic
import core.serialization.SerializedBytes import core.serialization.SerializedBytes
import core.utilities.ANSIProgressRenderer import core.utilities.ANSIProgressRenderer
@ -14,7 +18,7 @@ import java.util.*
import kotlin.reflect.KParameter import kotlin.reflect.KParameter
import kotlin.reflect.jvm.javaType import kotlin.reflect.jvm.javaType
class APIServerImpl(val node: AbstractNode): APIServer { class APIServerImpl(val node: AbstractNode) : APIServer {
override fun serverTime(): LocalDateTime = LocalDateTime.now(node.services.clock) override fun serverTime(): LocalDateTime = LocalDateTime.now(node.services.clock)
@ -26,10 +30,9 @@ class APIServerImpl(val node: AbstractNode): APIServer {
if (query.criteria is StatesQuery.Criteria.AllDeals) { if (query.criteria is StatesQuery.Criteria.AllDeals) {
val states = node.services.walletService.linearHeads val states = node.services.walletService.linearHeads
return states.values.map { it.ref } return states.values.map { it.ref }
} } else if (query.criteria is StatesQuery.Criteria.Deal) {
else if (query.criteria is StatesQuery.Criteria.Deal) { val states = node.services.walletService.linearHeadsOfType<DealState>().filterValues {
val states = node.services.walletService.linearHeadsInstanceOf(DealState::class.java) { it.state.ref == query.criteria.ref
it.ref == query.criteria.ref
} }
return states.values.map { it.ref } return states.values.map { it.ref }
} }
@ -62,9 +65,9 @@ class APIServerImpl(val node: AbstractNode): APIServer {
} }
private fun invokeProtocolAsync(type: ProtocolRef, args: Map<String, Any?>): ListenableFuture<out Any?> { private fun invokeProtocolAsync(type: ProtocolRef, args: Map<String, Any?>): ListenableFuture<out Any?> {
if(type is ProtocolClassRef) { if (type is ProtocolClassRef) {
val clazz = Class.forName(type.className) val clazz = Class.forName(type.className)
if(ProtocolLogic::class.java.isAssignableFrom(clazz)) { if (ProtocolLogic::class.java.isAssignableFrom(clazz)) {
// TODO for security, check annotated as exposed on API? Or have PublicProtocolLogic... etc // TODO for security, check annotated as exposed on API? Or have PublicProtocolLogic... etc
nextConstructor@ for (constructor in clazz.kotlin.constructors) { nextConstructor@ for (constructor in clazz.kotlin.constructors) {
val params = HashMap<KParameter, Any?>() val params = HashMap<KParameter, Any?>()
@ -91,7 +94,7 @@ class APIServerImpl(val node: AbstractNode): APIServer {
// If we get here then we matched every parameter // If we get here then we matched every parameter
val protocol = constructor.callBy(params) as ProtocolLogic<*> val protocol = constructor.callBy(params) as ProtocolLogic<*>
ANSIProgressRenderer.progressTracker = protocol.progressTracker ANSIProgressRenderer.progressTracker = protocol.progressTracker
val future = node.smm.add("api-call",protocol) val future = node.smm.add("api-call", protocol)
return future return future
} }
} }

View File

@ -11,7 +11,7 @@ import javax.ws.rs.ext.Provider
* and to organise serializers / deserializers for java.time.* classes as necessary * and to organise serializers / deserializers for java.time.* classes as necessary
*/ */
@Provider @Provider
class Config(val services: ServiceHub): ContextResolver<ObjectMapper> { class Config(val services: ServiceHub) : ContextResolver<ObjectMapper> {
val defaultObjectMapper = JsonSupport.createDefaultMapper(services.identityService) val defaultObjectMapper = JsonSupport.createDefaultMapper(services.identityService)
override fun getContext(type: java.lang.Class<*>) = defaultObjectMapper override fun getContext(type: java.lang.Class<*>) = defaultObjectMapper
} }

View File

@ -36,13 +36,13 @@ class InterestRateSwapAPI(val api: APIServer) {
private val logger = loggerFor<InterestRateSwapAPI>() private val logger = loggerFor<InterestRateSwapAPI>()
private fun generateDealLink(deal: InterestRateSwap.State) = "/api/irs/deals/"+deal.common.tradeID private fun generateDealLink(deal: InterestRateSwap.State) = "/api/irs/deals/" + deal.common.tradeID
private fun getDealByRef(ref: String): InterestRateSwap.State? { private fun getDealByRef(ref: String): InterestRateSwap.State? {
val states = api.queryStates(StatesQuery.selectDeal(ref)) val states = api.queryStates(StatesQuery.selectDeal(ref))
return if (states.isEmpty()) null else { return if (states.isEmpty()) null else {
val deals = api.fetchStates(states).values.map { it as InterestRateSwap.State}.filterNotNull() val deals = api.fetchStates(states).values.map { it as InterestRateSwap.State }.filterNotNull()
return if(deals.isEmpty()) null else deals[0] return if (deals.isEmpty()) null else deals[0]
} }
} }
@ -83,7 +83,7 @@ class InterestRateSwapAPI(val api: APIServer) {
fun storeDemoDate(newDemoDate: LocalDate): Response { fun storeDemoDate(newDemoDate: LocalDate): Response {
val priorDemoDate = api.serverTime().toLocalDate() val priorDemoDate = api.serverTime().toLocalDate()
// Can only move date forwards // Can only move date forwards
if(newDemoDate.isAfter(priorDemoDate)) { if (newDemoDate.isAfter(priorDemoDate)) {
api.invokeProtocolSync(ProtocolClassRef(UpdateBusinessDayProtocol.Broadcast::class.java.name!!), mapOf("date" to newDemoDate)) api.invokeProtocolSync(ProtocolClassRef(UpdateBusinessDayProtocol.Broadcast::class.java.name!!), mapOf("date" to newDemoDate))
return Response.ok().build() return Response.ok().build()
} }

View File

@ -1,18 +1,9 @@
/*
* Copyright 2016 Distributed Ledger Group LLC. Distributed as Licensed Company IP to DLG Group Members
* pursuant to the August 7, 2015 Advisory Services Agreement and subject to the Company IP License terms
* set forth therein.
*
* All other rights reserved.
*/
package api package api
/** /**
* Extremely rudimentary query language which should most likely be replaced with a product * Extremely rudimentary query language which should most likely be replaced with a product
*/ */
interface StatesQuery { interface StatesQuery {
companion object { companion object {
fun select(criteria: Criteria): Selection { fun select(criteria: Criteria): Selection {
return Selection(criteria) return Selection(criteria)
@ -29,13 +20,11 @@ interface StatesQuery {
} }
// TODO make constructors private // TODO make constructors private
data class Selection(val criteria: Criteria): StatesQuery data class Selection(val criteria: Criteria) : StatesQuery
interface Criteria { interface Criteria {
object AllDeals : Criteria
object AllDeals: Criteria data class Deal(val ref: String) : Criteria
data class Deal(val ref: String): Criteria
} }
} }

View File

@ -9,7 +9,7 @@ import javax.ws.rs.ext.Provider
* This adds headers needed for cross site scripting on API clients * This adds headers needed for cross site scripting on API clients
*/ */
@Provider @Provider
class ResponseFilter: ContainerResponseFilter { class ResponseFilter : ContainerResponseFilter {
override fun filter(requestContext: ContainerRequestContext, responseContext: ContainerResponseContext) { override fun filter(requestContext: ContainerRequestContext, responseContext: ContainerResponseContext) {
val headers = responseContext.headers val headers = responseContext.headers
@ -21,9 +21,9 @@ class ResponseFilter: ContainerResponseFilter {
* access control and authentication at a network and software level * access control and authentication at a network and software level
* *
*/ */
headers.add("Access-Control-Allow-Origin","*") headers.add("Access-Control-Allow-Origin", "*")
if(requestContext.method == "OPTIONS") { if (requestContext.method == "OPTIONS") {
headers.add("Access-Control-Allow-Headers", "Content-Type,Accept,Origin") headers.add("Access-Control-Allow-Headers", "Content-Type,Accept,Origin")
headers.add("Access-Control-Allow-Methods", "POST,PUT,GET,OPTIONS") headers.add("Access-Control-Allow-Methods", "POST,PUT,GET,OPTIONS")
} }

View File

@ -1,11 +1,3 @@
/*
* Copyright 2015 Distributed Ledger Group LLC. Distributed as Licensed Company IP to DLG Group Members
* pursuant to the August 7, 2015 Advisory Services Agreement and subject to the Company IP License terms
* set forth therein.
*
* All other rights reserved.
*/
package core package core
import core.node.services.AttachmentStorage import core.node.services.AttachmentStorage

View File

@ -1,11 +1,3 @@
/*
* Copyright 2015 Distributed Ledger Group LLC. Distributed as Licensed Company IP to DLG Group Members
* pursuant to the August 7, 2015 Advisory Services Agreement and subject to the Company IP License terms
* set forth therein.
*
* All other rights reserved.
*/
package core.messaging package core.messaging
import com.google.common.util.concurrent.ListenableFuture import com.google.common.util.concurrent.ListenableFuture
@ -128,9 +120,12 @@ object TopicStringValidator {
/** The interface for a group of message recipients (which may contain only one recipient) */ /** The interface for a group of message recipients (which may contain only one recipient) */
interface MessageRecipients interface MessageRecipients
/** A base class for the case of point-to-point messages */ /** A base class for the case of point-to-point messages */
interface SingleMessageRecipient : MessageRecipients interface SingleMessageRecipient : MessageRecipients
/** A base class for a set of recipients specifically identified by the sender. */ /** A base class for a set of recipients specifically identified by the sender. */
interface MessageRecipientGroup : MessageRecipients interface MessageRecipientGroup : MessageRecipients
/** A special base class for the set of all possible recipients, without having to identify who they all are. */ /** A special base class for the set of all possible recipients, without having to identify who they all are. */
interface AllPossibleRecipients : MessageRecipients interface AllPossibleRecipients : MessageRecipients

View File

@ -1,11 +1,3 @@
/*
* Copyright 2015 Distributed Ledger Group LLC. Distributed as Licensed Company IP to DLG Group Members
* pursuant to the August 7, 2015 Advisory Services Agreement and subject to the Company IP License terms
* set forth therein.
*
* All other rights reserved.
*/
package core.messaging package core.messaging
import co.paralleluniverse.fibers.Fiber import co.paralleluniverse.fibers.Fiber
@ -68,22 +60,15 @@ class StateMachineManager(val serviceHub: ServiceHub, val runInThread: Executor)
// Monitoring support. // Monitoring support.
private val metrics = serviceHub.monitoringService.metrics private val metrics = serviceHub.monitoringService.metrics
init { metrics.register("Protocols.InFlight", Gauge<kotlin.Int> { _stateMachines.size }) }
init {
metrics.register("Protocols.InFlight", Gauge<kotlin.Int> { _stateMachines.size })
}
private val checkpointingMeter = metrics.meter("Protocols.Checkpointing Rate") private val checkpointingMeter = metrics.meter("Protocols.Checkpointing Rate")
private val totalStartedProtocols = metrics.counter("Protocols.Started") private val totalStartedProtocols = metrics.counter("Protocols.Started")
private val totalFinishedProtocols = metrics.counter("Protocols.Finished") private val totalFinishedProtocols = metrics.counter("Protocols.Finished")
// This is a workaround for something Gradle does to us during unit tests. It replaces stderr with its own
// class that inserts itself into a ThreadLocal. That then gets caught in fiber serialisation, which we don't
// want because it can't get recreated properly. It turns out there's no good workaround for this! All the obvious
// approaches fail. Pending resolution of https://github.com/puniverse/quasar/issues/153 we just disable
// checkpointing when unit tests are run inside Gradle. The right fix is probably to stop Quasar's
// bit-too-clever-for-its-own-good ThreadLocal serialisation trick. It already wasted far more time than it can
// ever recover.
//
// TODO: Remove this now that TLS serialisation is fixed.
val checkpointing: Boolean get() = !System.err.javaClass.name.contains("LinePerThreadBufferingOutputStream")
/** Returns a list of all state machines executing the given protocol logic at the top level (subprotocols do not count) */ /** Returns a list of all state machines executing the given protocol logic at the top level (subprotocols do not count) */
fun <T> findStateMachines(klass: Class<out ProtocolLogic<T>>): List<Pair<ProtocolLogic<T>, ListenableFuture<T>>> { fun <T> findStateMachines(klass: Class<out ProtocolLogic<T>>): List<Pair<ProtocolLogic<T>, ListenableFuture<T>>> {
synchronized(_stateMachines) { synchronized(_stateMachines) {
@ -111,8 +96,6 @@ class StateMachineManager(val serviceHub: ServiceHub, val runInThread: Executor)
// Blank out the default uncaught exception handler because we always catch things ourselves, and the default // Blank out the default uncaught exception handler because we always catch things ourselves, and the default
// just redundantly prints stack traces to the logs. // just redundantly prints stack traces to the logs.
Fiber.setDefaultUncaughtExceptionHandler { fiber, throwable -> } Fiber.setDefaultUncaughtExceptionHandler { fiber, throwable -> }
if (checkpointing)
restoreCheckpoints() restoreCheckpoints()
} }
@ -235,7 +218,6 @@ class StateMachineManager(val serviceHub: ServiceHub, val runInThread: Executor)
serialisedFiber: ByteArray) { serialisedFiber: ByteArray) {
val checkpoint = Checkpoint(serialisedFiber, logger.name, topic, responseType.name) val checkpoint = Checkpoint(serialisedFiber, logger.name, topic, responseType.name)
val curPersistedBytes = checkpoint.serialize().bits val curPersistedBytes = checkpoint.serialize().bits
if (checkpointing)
persistCheckpoint(prevCheckpointKey, curPersistedBytes) persistCheckpoint(prevCheckpointKey, curPersistedBytes)
val newCheckpointKey = curPersistedBytes.sha256() val newCheckpointKey = curPersistedBytes.sha256()
net.runOnNextMessage(topic, runInThread) { netMsg -> net.runOnNextMessage(topic, runInThread) { netMsg ->

View File

@ -1,19 +1,3 @@
/*
* Copyright 2015 Distributed Ledger Group LLC. Distributed as Licensed Company IP to DLG Group Members
* pursuant to the August 7, 2015 Advisory Services Agreement and subject to the Company IP License terms
* set forth therein.
*
* All other rights reserved.
*/
/*
* Copyright 2015 Distributed Ledger Group LLC. Distributed as Licensed Company IP to DLG Group Members
* pursuant to the August 7, 2015 Advisory Services Agreement and subject to the Company IP License terms
* set forth therein.
*
* All other rights reserved.
*/
package core.node package core.node
import api.APIServer import api.APIServer

View File

@ -1,11 +1,3 @@
/*
* Copyright 2015 Distributed Ledger Group LLC. Distributed as Licensed Company IP to DLG Group Members
* pursuant to the August 7, 2015 Advisory Services Agreement and subject to the Company IP License terms
* set forth therein.
*
* All other rights reserved.
*/
package core.node package core.node
import java.io.InputStream import java.io.InputStream

View File

@ -1,11 +1,3 @@
/*
* Copyright 2015 Distributed Ledger Group LLC. Distributed as Licensed Company IP to DLG Group Members
* pursuant to the August 7, 2015 Advisory Services Agreement and subject to the Company IP License terms
* set forth therein.
*
* All other rights reserved.
*/
package core.node package core.node
import api.Config import api.Config

View File

@ -1,11 +1,3 @@
/*
* Copyright 2015 Distributed Ledger Group LLC. Distributed as Licensed Company IP to DLG Group Members
* pursuant to the August 7, 2015 Advisory Services Agreement and subject to the Company IP License terms
* set forth therein.
*
* All other rights reserved.
*/
package core.node package core.node
import com.typesafe.config.Config import com.typesafe.config.Config

View File

@ -1,11 +1,3 @@
/*
* Copyright 2015 Distributed Ledger Group LLC. Distributed as Licensed Company IP to DLG Group Members
* pursuant to the August 7, 2015 Advisory Services Agreement and subject to the Company IP License terms
* set forth therein.
*
* All other rights reserved.
*/
package core.node.services package core.node.services
import com.google.common.net.HostAndPort import com.google.common.net.HostAndPort
@ -82,11 +74,13 @@ class ArtemisMessagingService(val directory: Path, val myHostPort: HostAndPort)
var running = false var running = false
val sendClients = HashMap<Address, ClientProducer>() val sendClients = HashMap<Address, ClientProducer>()
} }
private val mutex = ThreadBox(InnerState()) private val mutex = ThreadBox(InnerState())
/** A registration to handle messages of different types */ /** A registration to handle messages of different types */
inner class Handler(val executor: Executor?, val topic: String, inner class Handler(val executor: Executor?, val topic: String,
val callback: (Message, MessageHandlerRegistration) -> Unit) : MessageHandlerRegistration val callback: (Message, MessageHandlerRegistration) -> Unit) : MessageHandlerRegistration
private val handlers = CopyOnWriteArrayList<Handler>() private val handlers = CopyOnWriteArrayList<Handler>()
private fun getSendClient(addr: Address): ClientProducer { private fun getSendClient(addr: Address): ClientProducer {

View File

@ -1,16 +1,5 @@
/*
* Copyright 2015 Distributed Ledger Group LLC. Distributed as Licensed Company IP to DLG Group Members
* pursuant to the August 7, 2015 Advisory Services Agreement and subject to the Company IP License terms
* set forth therein.
*
* All other rights reserved.
*/
package core.node.services package core.node.services
import protocols.FetchAttachmentsProtocol
import protocols.FetchTransactionsProtocol
import core.node.services.StorageService
import core.crypto.SecureHash import core.crypto.SecureHash
import core.messaging.Message import core.messaging.Message
import core.messaging.MessagingService import core.messaging.MessagingService
@ -18,6 +7,8 @@ import core.messaging.SingleMessageRecipient
import core.messaging.send import core.messaging.send
import core.serialization.deserialize import core.serialization.deserialize
import core.utilities.loggerFor import core.utilities.loggerFor
import protocols.FetchAttachmentsProtocol
import protocols.FetchTransactionsProtocol
import java.io.InputStream import java.io.InputStream
import javax.annotation.concurrent.ThreadSafe import javax.annotation.concurrent.ThreadSafe

View File

@ -1,14 +1,5 @@
/*
* Copyright 2015 Distributed Ledger Group LLC. Distributed as Licensed Company IP to DLG Group Members
* pursuant to the August 7, 2015 Advisory Services Agreement and subject to the Company IP License terms
* set forth therein.
*
* All other rights reserved.
*/
package core.node.services package core.node.services
import core.node.services.KeyManagementService
import core.ThreadBox import core.ThreadBox
import core.crypto.generateKeyPair import core.crypto.generateKeyPair
import java.security.KeyPair import java.security.KeyPair
@ -33,6 +24,7 @@ class E2ETestKeyManagementService : KeyManagementService {
private class InnerState { private class InnerState {
val keys = HashMap<PublicKey, PrivateKey>() val keys = HashMap<PublicKey, PrivateKey>()
} }
private val mutex = ThreadBox(InnerState()) private val mutex = ThreadBox(InnerState())
// Accessing this map clones it. // Accessing this map clones it.

View File

@ -1,11 +1,3 @@
/*
* Copyright 2015 Distributed Ledger Group LLC. Distributed as Licensed Company IP to DLG Group Members
* pursuant to the August 7, 2015 Advisory Services Agreement and subject to the Company IP License terms
* set forth therein.
*
* All other rights reserved.
*/
package core.node.services package core.node.services
import core.Party import core.Party

View File

@ -1,11 +1,3 @@
/*
* Copyright 2015 Distributed Ledger Group LLC. Distributed as Licensed Company IP to DLG Group Members
* pursuant to the August 7, 2015 Advisory Services Agreement and subject to the Company IP License terms
* set forth therein.
*
* All other rights reserved.
*/
package core.node.services package core.node.services
import core.Party import core.Party
@ -27,7 +19,7 @@ data class NodeInfo(val address: SingleMessageRecipient, val identity: Party,
* then be cached by every node and thus a network map can be retrieved given only a single successful peer connection. * then be cached by every node and thus a network map can be retrieved given only a single successful peer connection.
* *
* This interface assumes fast, synchronous access to an in-memory map. * This interface assumes fast, synchronous access to an in-memory map.
*/ */
interface NetworkMapCache { interface NetworkMapCache {
val timestampingNodes: List<NodeInfo> val timestampingNodes: List<NodeInfo>
val ratesOracleNodes: List<NodeInfo> val ratesOracleNodes: List<NodeInfo>
@ -39,7 +31,7 @@ interface NetworkMapCache {
// TODO: Move this to the test tree once a real network map is implemented and this scaffolding is no longer needed. // TODO: Move this to the test tree once a real network map is implemented and this scaffolding is no longer needed.
class MockNetworkMapCache : NetworkMapCache { class MockNetworkMapCache : NetworkMapCache {
data class MockAddress(val id: String): SingleMessageRecipient data class MockAddress(val id: String) : SingleMessageRecipient
override val timestampingNodes = Collections.synchronizedList(ArrayList<NodeInfo>()) override val timestampingNodes = Collections.synchronizedList(ArrayList<NodeInfo>())
override val ratesOracleNodes = Collections.synchronizedList(ArrayList<NodeInfo>()) override val ratesOracleNodes = Collections.synchronizedList(ArrayList<NodeInfo>())

View File

@ -1,11 +1,3 @@
/*
* Copyright 2015 Distributed Ledger Group LLC. Distributed as Licensed Company IP to DLG Group Members
* pursuant to the August 7, 2015 Advisory Services Agreement and subject to the Company IP License terms
* set forth therein.
*
* All other rights reserved.
*/
package core.node.services package core.node.services
import com.codahale.metrics.MetricRegistry import com.codahale.metrics.MetricRegistry
@ -98,6 +90,7 @@ class NodeAttachmentService(val storePath: Path, val metrics: MetricRegistry) :
stream = HashCheckingStream(id, path, stream) stream = HashCheckingStream(id, path, stream)
return stream return stream
} }
override fun equals(other: Any?) = other is Attachment && other.id == id override fun equals(other: Any?) = other is Attachment && other.id == id
override fun hashCode(): Int = id.hashCode() override fun hashCode(): Int = id.hashCode()
} }

View File

@ -1,11 +1,3 @@
/*
* Copyright 2015 Distributed Ledger Group LLC. Distributed as Licensed Company IP to DLG Group Members
* pursuant to the August 7, 2015 Advisory Services Agreement and subject to the Company IP License terms
* set forth therein.
*
* All other rights reserved.
*/
package core.node.services package core.node.services
import core.* import core.*
@ -51,8 +43,8 @@ object NodeInterestRates {
} }
/** Parses lines containing fixes */ /** Parses lines containing fixes */
fun parseFile(s: String): Map<FixOf, TreeMap<LocalDate,Fix>> { fun parseFile(s: String): Map<FixOf, TreeMap<LocalDate, Fix>> {
val results = HashMap<FixOf, TreeMap<LocalDate,Fix>>() val results = HashMap<FixOf, TreeMap<LocalDate, Fix>>()
for (line in s.lines()) { for (line in s.lines()) {
val (fixOf, fix) = parseOneRate(line) val (fixOf, fix) = parseOneRate(line)
val genericKey = FixOf(fixOf.name, LocalDate.MIN, fixOf.ofTenor) val genericKey = FixOf(fixOf.name, LocalDate.MIN, fixOf.ofTenor)
@ -96,7 +88,7 @@ object NodeInterestRates {
override val acceptableFileExtensions = listOf(".rates", ".txt") override val acceptableFileExtensions = listOf(".rates", ".txt")
override fun upload(data: InputStream): String { override fun upload(data: InputStream): String {
val fixes: Map<FixOf, TreeMap<LocalDate,Fix>> = parseFile(data. val fixes: Map<FixOf, TreeMap<LocalDate, Fix>> = parseFile(data.
bufferedReader(). bufferedReader().
readLines(). readLines().
map { it.trim() }. map { it.trim() }.
@ -133,7 +125,7 @@ object NodeInterestRates {
* to a sorted map of LocalDate to Fix, allowing for approximate date finding so that we do not need * to a sorted map of LocalDate to Fix, allowing for approximate date finding so that we do not need
* to populate the file with a rate for every day. * to populate the file with a rate for every day.
*/ */
@Volatile var knownFixes = emptyMap<FixOf, TreeMap<LocalDate,Fix>>() @Volatile var knownFixes = emptyMap<FixOf, TreeMap<LocalDate, Fix>>()
set(value) { set(value) {
require(value.isNotEmpty()) require(value.isNotEmpty())
field = value field = value
@ -154,7 +146,7 @@ object NodeInterestRates {
val rates = knownFixes[FixOf(fixOf.name, LocalDate.MIN, fixOf.ofTenor)] val rates = knownFixes[FixOf(fixOf.name, LocalDate.MIN, fixOf.ofTenor)]
// Greatest key less than or equal to the date we're looking for // Greatest key less than or equal to the date we're looking for
val floor = rates?.floorEntry(fixOf.forDay)?.value val floor = rates?.floorEntry(fixOf.forDay)?.value
return if (floor!=null) { return if (floor != null) {
Fix(fixOf, floor.value) Fix(fixOf, floor.value)
} else { } else {
null null

View File

@ -1,11 +1,3 @@
/*
* Copyright 2015 Distributed Ledger Group LLC. Distributed as Licensed Company IP to DLG Group Members
* pursuant to the August 7, 2015 Advisory Services Agreement and subject to the Company IP License terms
* set forth therein.
*
* All other rights reserved.
*/
package core.node.services package core.node.services
import co.paralleluniverse.common.util.VisibleForTesting import co.paralleluniverse.common.util.VisibleForTesting

View File

@ -1,11 +1,3 @@
/*
* Copyright 2015 Distributed Ledger Group LLC. Distributed as Licensed Company IP to DLG Group Members
* pursuant to the August 7, 2015 Advisory Services Agreement and subject to the Company IP License terms
* set forth therein.
*
* All other rights reserved.
*/
package core.node.services package core.node.services
import com.codahale.metrics.Gauge import com.codahale.metrics.Gauge
@ -33,6 +25,7 @@ class NodeWalletService(private val services: ServiceHub) : WalletService {
private class InnerState { private class InnerState {
var wallet: Wallet = Wallet(emptyList<StateAndRef<OwnableState>>()) var wallet: Wallet = Wallet(emptyList<StateAndRef<OwnableState>>())
} }
private val mutex = ThreadBox(InnerState()) private val mutex = ThreadBox(InnerState())
override val currentWallet: Wallet get() = mutex.locked { wallet } override val currentWallet: Wallet get() = mutex.locked { wallet }
@ -48,7 +41,7 @@ class NodeWalletService(private val services: ServiceHub) : WalletService {
*/ */
override val linearHeads: Map<SecureHash, StateAndRef<LinearState>> override val linearHeads: Map<SecureHash, StateAndRef<LinearState>>
get() = mutex.locked { wallet }.let { wallet -> get() = mutex.locked { wallet }.let { wallet ->
wallet.states.filter { it.state is LinearState }.associateBy { (it.state as LinearState).thread }.mapValues { it.value as StateAndRef<LinearState> } wallet.states.filterStatesOfType<LinearState>().associateBy { it.state.thread }.mapValues { it.value }
} }
override fun notifyAll(txns: Iterable<WireTransaction>): Wallet { override fun notifyAll(txns: Iterable<WireTransaction>): Wallet {
@ -78,9 +71,9 @@ class NodeWalletService(private val services: ServiceHub) : WalletService {
} }
private fun isRelevant(state: ContractState, ourKeys: Set<PublicKey>): Boolean { private fun isRelevant(state: ContractState, ourKeys: Set<PublicKey>): Boolean {
return if(state is OwnableState) { return if (state is OwnableState) {
state.owner in ourKeys state.owner in ourKeys
} else if(state is LinearState) { } else if (state is LinearState) {
// It's potentially of interest to the wallet // It's potentially of interest to the wallet
state.isRelevant(ourKeys) state.isRelevant(ourKeys)
} else { } else {

View File

@ -1,11 +1,3 @@
/*
* Copyright 2015 Distributed Ledger Group LLC. Distributed as Licensed Company IP to DLG Group Members
* pursuant to the August 7, 2015 Advisory Services Agreement and subject to the Company IP License terms
* set forth therein.
*
* All other rights reserved.
*/
package core.node.services package core.node.services
import com.codahale.metrics.MetricRegistry import com.codahale.metrics.MetricRegistry
@ -72,13 +64,17 @@ interface WalletService {
*/ */
val linearHeads: Map<SecureHash, StateAndRef<LinearState>> val linearHeads: Map<SecureHash, StateAndRef<LinearState>>
fun <T : LinearState> linearHeadsInstanceOf(clazz: Class<T>, predicate: (T) -> Boolean = { true } ): Map<SecureHash, StateAndRef<T>> { // TODO: When KT-10399 is fixed, rename this and remove the inline version below.
return linearHeads.filterValues { clazz.isInstance(it.state) }.filterValues { predicate(it.state as T) }.mapValues { StateAndRef(it.value.state as T, it.value.ref) }
/** Returns the [linearHeads] only when the type of the state would be considered an 'instanceof' the given type. */
@Suppress("UNCHECKED_CAST")
fun <T : LinearState> linearHeadsOfType_(stateType: Class<T>): Map<SecureHash, StateAndRef<T>> {
return linearHeads.filterValues { stateType.isInstance(it.state) }.mapValues { StateAndRef(it.value.state as T, it.value.ref) }
} }
fun statesForRefs(refs: List<StateRef>): Map<StateRef, ContractState?> { fun statesForRefs(refs: List<StateRef>): Map<StateRef, ContractState?> {
val refsToStates = currentWallet.states.associateBy { it.ref } val refsToStates = currentWallet.states.associateBy { it.ref }
return refs.associateBy( { it }, { refsToStates[it]?.state } ) return refs.associateBy({ it }, { refsToStates[it]?.state })
} }
/** /**
@ -95,17 +91,7 @@ interface WalletService {
fun notify(tx: WireTransaction): Wallet = notifyAll(listOf(tx)) fun notify(tx: WireTransaction): Wallet = notifyAll(listOf(tx))
} }
// TODO: Document this inline fun <reified T : LinearState> WalletService.linearHeadsOfType() = linearHeadsOfType_(T::class.java)
@Suppress("UNCHECKED_CAST")
inline fun <reified T : LinearState> WalletService.linearHeadsOfType(): Map<SecureHash, StateAndRef<T>> {
return linearHeads.mapNotNull {
val s = it.value.state
if (s is T)
Pair(it.key, it.value as StateAndRef<T>)
else
null
}.toMap()
}
/** /**
* The KMS is responsible for storing and using private keys to sign things. An implementation of this may, for example, * The KMS is responsible for storing and using private keys to sign things. An implementation of this may, for example,

View File

@ -14,12 +14,13 @@ open class StorageServiceImpl(attachments: AttachmentStorage,
// This parameter is for unit tests that want to observe operation details. // This parameter is for unit tests that want to observe operation details.
val recordingAs: (String) -> String = { tableName -> "" }) val recordingAs: (String) -> String = { tableName -> "" })
: StorageService { : StorageService {
protected val tables = HashMap<String, MutableMap<Any, Any>>() protected val tables = HashMap<String, MutableMap<*, *>>()
private fun <K, V> getMapOriginal(tableName: String): MutableMap<K, V> { private fun <K, V> getMapOriginal(tableName: String): MutableMap<K, V> {
synchronized(tables) { synchronized(tables) {
@Suppress("UNCHECKED_CAST")
return tables.getOrPut(tableName) { return tables.getOrPut(tableName) {
recorderWrap(Collections.synchronizedMap(HashMap<Any, Any>()), tableName); recorderWrap(Collections.synchronizedMap(HashMap<K, V>()), tableName)
} as MutableMap<K, V> } as MutableMap<K, V>
} }
} }

View File

@ -1,15 +1,7 @@
/*
* Copyright 2015 Distributed Ledger Group LLC. Distributed as Licensed Company IP to DLG Group Members
* pursuant to the August 7, 2015 Advisory Services Agreement and subject to the Company IP License terms
* set forth therein.
*
* All other rights reserved.
*/
package core.node.servlets package core.node.servlets
import core.node.services.StorageService
import core.crypto.SecureHash import core.crypto.SecureHash
import core.node.services.StorageService
import core.utilities.loggerFor import core.utilities.loggerFor
import java.io.FileNotFoundException import java.io.FileNotFoundException
import javax.servlet.http.HttpServlet import javax.servlet.http.HttpServlet

View File

@ -1,11 +1,3 @@
/*
* Copyright 2015 Distributed Ledger Group LLC. Distributed as Licensed Company IP to DLG Group Members
* pursuant to the August 7, 2015 Advisory Services Agreement and subject to the Company IP License terms
* set forth therein.
*
* All other rights reserved.
*/
package core.node.servlets package core.node.servlets
import core.node.AcceptsFileUpload import core.node.AcceptsFileUpload

View File

@ -1,16 +1,8 @@
/*
* Copyright 2015 Distributed Ledger Group LLC. Distributed as Licensed Company IP to DLG Group Members
* pursuant to the August 7, 2015 Advisory Services Agreement and subject to the Company IP License terms
* set forth therein.
*
* All other rights reserved.
*/
package core.protocols package core.protocols
import co.paralleluniverse.fibers.Suspendable import co.paralleluniverse.fibers.Suspendable
import core.node.services.ServiceHub
import core.messaging.MessageRecipients import core.messaging.MessageRecipients
import core.node.services.ServiceHub
import core.utilities.ProgressTracker import core.utilities.ProgressTracker
import core.utilities.UntrustworthyData import core.utilities.UntrustworthyData
import org.slf4j.Logger import org.slf4j.Logger
@ -47,12 +39,15 @@ abstract class ProtocolLogic<T> {
sessionIDForReceive: Long, obj: Any): UntrustworthyData<T> { sessionIDForReceive: Long, obj: Any): UntrustworthyData<T> {
return psm.sendAndReceive(topic, destination, sessionIDForSend, sessionIDForReceive, obj, T::class.java) return psm.sendAndReceive(topic, destination, sessionIDForSend, sessionIDForReceive, obj, T::class.java)
} }
inline fun <reified T : Any> receive(topic: String, sessionIDForReceive: Long): UntrustworthyData<T> { inline fun <reified T : Any> receive(topic: String, sessionIDForReceive: Long): UntrustworthyData<T> {
return receive(topic, sessionIDForReceive, T::class.java) return receive(topic, sessionIDForReceive, T::class.java)
} }
@Suspendable fun <T : Any> receive(topic: String, sessionIDForReceive: Long, clazz: Class<T>): UntrustworthyData<T> { @Suspendable fun <T : Any> receive(topic: String, sessionIDForReceive: Long, clazz: Class<T>): UntrustworthyData<T> {
return psm.receive(topic, sessionIDForReceive, clazz) return psm.receive(topic, sessionIDForReceive, clazz)
} }
@Suspendable fun send(topic: String, destination: MessageRecipients, sessionID: Long, obj: Any) { @Suspendable fun send(topic: String, destination: MessageRecipients, sessionID: Long, obj: Any) {
psm.send(topic, destination, sessionID, obj) psm.send(topic, destination, sessionID, obj)
} }

View File

@ -1,11 +1,3 @@
/*
* Copyright 2015 Distributed Ledger Group LLC. Distributed as Licensed Company IP to DLG Group Members
* pursuant to the August 7, 2015 Advisory Services Agreement and subject to the Company IP License terms
* set forth therein.
*
* All other rights reserved.
*/
package core.protocols package core.protocols
import co.paralleluniverse.fibers.Fiber import co.paralleluniverse.fibers.Fiber
@ -14,9 +6,9 @@ import co.paralleluniverse.io.serialization.kryo.KryoSerializer
import com.esotericsoftware.kryo.io.Output import com.esotericsoftware.kryo.io.Output
import com.google.common.util.concurrent.ListenableFuture import com.google.common.util.concurrent.ListenableFuture
import com.google.common.util.concurrent.SettableFuture import com.google.common.util.concurrent.SettableFuture
import core.node.services.ServiceHub
import core.messaging.MessageRecipients import core.messaging.MessageRecipients
import core.messaging.StateMachineManager import core.messaging.StateMachineManager
import core.node.services.ServiceHub
import core.serialization.createKryo import core.serialization.createKryo
import core.utilities.UntrustworthyData import core.utilities.UntrustworthyData
import org.slf4j.Logger import org.slf4j.Logger

View File

@ -1,11 +1,3 @@
/*
* Copyright 2015 Distributed Ledger Group LLC. Distributed as Licensed Company IP to DLG Group Members
* pursuant to the August 7, 2015 Advisory Services Agreement and subject to the Company IP License terms
* set forth therein.
*
* All other rights reserved.
*/
package core.testing package core.testing
import com.fasterxml.jackson.module.kotlin.readValue import com.fasterxml.jackson.module.kotlin.readValue

View File

@ -1,11 +1,3 @@
/*
* Copyright 2015 Distributed Ledger Group LLC. Distributed as Licensed Company IP to DLG Group Members
* pursuant to the August 7, 2015 Advisory Services Agreement and subject to the Company IP License terms
* set forth therein.
*
* All other rights reserved.
*/
package core.testing package core.testing
import com.google.common.util.concurrent.Futures import com.google.common.util.concurrent.Futures
@ -59,7 +51,7 @@ class InMemoryMessagingNetwork {
*/ */
@Synchronized @Synchronized
fun createNode(manuallyPumped: Boolean): Pair<Handle, MessagingServiceBuilder<InMemoryMessaging>> { fun createNode(manuallyPumped: Boolean): Pair<Handle, MessagingServiceBuilder<InMemoryMessaging>> {
check(counter >= 0) { "In memory network stopped: please recreate."} check(counter >= 0) { "In memory network stopped: please recreate." }
val builder = createNodeWithID(manuallyPumped, counter) as Builder val builder = createNodeWithID(manuallyPumped, counter) as Builder
counter++ counter++
val id = builder.id val id = builder.id
@ -89,15 +81,15 @@ class InMemoryMessagingNetwork {
if (calc != null && recipients is SingleMessageRecipient) { if (calc != null && recipients is SingleMessageRecipient) {
// Inject some artificial latency. // Inject some artificial latency.
timer.schedule(calc.between(from.myAddress, recipients).toMillis()) { timer.schedule(calc.between(from.myAddress, recipients).toMillis()) {
msgSendInternal(from, message, recipients) msgSendInternal(message, recipients)
} }
} else { } else {
msgSendInternal(from, message, recipients) msgSendInternal(message, recipients)
} }
_allMessages.onNext(Triple(from.myAddress, message, recipients)) _allMessages.onNext(Triple(from.myAddress, message, recipients))
} }
private fun msgSendInternal(from: InMemoryMessaging, message: Message, recipients: MessageRecipients) { private fun msgSendInternal(message: Message, recipients: MessageRecipients) {
when (recipients) { when (recipients) {
is Handle -> getQueueForHandle(recipients).add(message) is Handle -> getQueueForHandle(recipients).add(message)
@ -170,15 +162,18 @@ class InMemoryMessagingNetwork {
* An instance can be obtained by creating a builder and then using the start method. * An instance can be obtained by creating a builder and then using the start method.
*/ */
@ThreadSafe @ThreadSafe
inner class InMemoryMessaging(private val manuallyPumped: Boolean, private val handle: Handle): MessagingService { inner class InMemoryMessaging(private val manuallyPumped: Boolean, private val handle: Handle) : MessagingService {
inner class Handler(val executor: Executor?, val topic: String, inner class Handler(val executor: Executor?, val topic: String,
val callback: (Message, MessageHandlerRegistration) -> Unit) : MessageHandlerRegistration val callback: (Message, MessageHandlerRegistration) -> Unit) : MessageHandlerRegistration
@Volatile @Volatile
protected var running = true protected var running = true
protected inner class InnerState { protected inner class InnerState {
val handlers: MutableList<Handler> = ArrayList() val handlers: MutableList<Handler> = ArrayList()
val pendingRedelivery = LinkedList<Message>() val pendingRedelivery = LinkedList<Message>()
} }
protected val state = ThreadBox(InnerState()) protected val state = ThreadBox(InnerState())
override val myAddress: SingleMessageRecipient = handle override val myAddress: SingleMessageRecipient = handle

View File

@ -1,11 +1,3 @@
/*
* Copyright 2015 Distributed Ledger Group LLC. Distributed as Licensed Company IP to DLG Group Members
* pursuant to the August 7, 2015 Advisory Services Agreement and subject to the Company IP License terms
* set forth therein.
*
* All other rights reserved.
*/
package core.testing package core.testing
import com.google.common.jimfs.Jimfs import com.google.common.jimfs.Jimfs
@ -124,7 +116,8 @@ class MockNetwork(private val threadPerNode: Boolean = false,
fun runNetwork(rounds: Int = -1) { fun runNetwork(rounds: Int = -1) {
fun pumpAll() = messagingNetwork.endpoints.map { it.pump(false) } fun pumpAll() = messagingNetwork.endpoints.map { it.pump(false) }
if (rounds == -1) if (rounds == -1)
while (pumpAll().any { it }) {} while (pumpAll().any { it }) {
}
else else
repeat(rounds) { pumpAll() } repeat(rounds) { pumpAll() }
} }

View File

@ -1,11 +1,3 @@
/*
* Copyright 2015 Distributed Ledger Group LLC. Distributed as Licensed Company IP to DLG Group Members
* pursuant to the August 7, 2015 Advisory Services Agreement and subject to the Company IP License terms
* set forth therein.
*
* All other rights reserved.
*/
package core.testing package core.testing
import com.google.common.util.concurrent.ListenableFuture import com.google.common.util.concurrent.ListenableFuture
@ -190,7 +182,8 @@ abstract class Simulation(val runAsync: Boolean,
} }
} }
open fun start() {} open fun start() {
}
fun stop() { fun stop() {
network.nodes.forEach { it.stop() } network.nodes.forEach { it.stop() }

View File

@ -1,11 +1,3 @@
/*
* Copyright 2015 Distributed Ledger Group LLC. Distributed as Licensed Company IP to DLG Group Members
* pursuant to the August 7, 2015 Advisory Services Agreement and subject to the Company IP License terms
* set forth therein.
*
* All other rights reserved.
*/
package core.testing package core.testing
import com.google.common.util.concurrent.Futures import com.google.common.util.concurrent.Futures

View File

@ -1,11 +1,3 @@
/*
* Copyright 2015 Distributed Ledger Group LLC. Distributed as Licensed Company IP to DLG Group Members
* pursuant to the August 7, 2015 Advisory Services Agreement and subject to the Company IP License terms
* set forth therein.
*
* All other rights reserved.
*/
package core.utilities package core.utilities
import org.fusesource.jansi.Ansi import org.fusesource.jansi.Ansi

View File

@ -1,11 +1,3 @@
/*
* Copyright 2015 Distributed Ledger Group LLC. Distributed as Licensed Company IP to DLG Group Members
* pursuant to the August 7, 2015 Advisory Services Agreement and subject to the Company IP License terms
* set forth therein.
*
* All other rights reserved.
*/
package core.utilities package core.utilities
import com.fasterxml.jackson.core.JsonGenerator import com.fasterxml.jackson.core.JsonGenerator
@ -59,15 +51,15 @@ object JsonSupport {
return mapper return mapper
} }
class ServiceHubObjectMapper(val identities: IdentityService): ObjectMapper() class ServiceHubObjectMapper(val identities: IdentityService) : ObjectMapper()
object ToStringSerializer: JsonSerializer<Any>() { object ToStringSerializer : JsonSerializer<Any>() {
override fun serialize(obj: Any, generator: JsonGenerator, provider: SerializerProvider) { override fun serialize(obj: Any, generator: JsonGenerator, provider: SerializerProvider) {
generator.writeString(obj.toString()) generator.writeString(obj.toString())
} }
} }
object LocalDateDeserializer: JsonDeserializer<LocalDate>() { object LocalDateDeserializer : JsonDeserializer<LocalDate>() {
override fun deserialize(parser: JsonParser, context: DeserializationContext): LocalDate { override fun deserialize(parser: JsonParser, context: DeserializationContext): LocalDate {
return try { return try {
LocalDate.parse(parser.text) LocalDate.parse(parser.text)
@ -77,22 +69,22 @@ object JsonSupport {
} }
} }
object LocalDateKeyDeserializer: KeyDeserializer() { object LocalDateKeyDeserializer : KeyDeserializer() {
override fun deserializeKey(text: String, p1: DeserializationContext): Any? { override fun deserializeKey(text: String, p1: DeserializationContext): Any? {
return LocalDate.parse(text) return LocalDate.parse(text)
} }
} }
object PartySerializer: JsonSerializer<Party>() { object PartySerializer : JsonSerializer<Party>() {
override fun serialize(obj: Party, generator: JsonGenerator, provider: SerializerProvider) { override fun serialize(obj: Party, generator: JsonGenerator, provider: SerializerProvider) {
generator.writeString(obj.name) generator.writeString(obj.name)
} }
} }
object PartyDeserializer: JsonDeserializer<Party>() { object PartyDeserializer : JsonDeserializer<Party>() {
override fun deserialize(parser: JsonParser, context: DeserializationContext): Party { override fun deserialize(parser: JsonParser, context: DeserializationContext): Party {
if(parser.currentToken == JsonToken.FIELD_NAME) { if (parser.currentToken == JsonToken.FIELD_NAME) {
parser.nextToken() parser.nextToken()
} }
val mapper = parser.codec as ServiceHubObjectMapper val mapper = parser.codec as ServiceHubObjectMapper
@ -101,7 +93,7 @@ object JsonSupport {
} }
} }
object SecureHashSerializer: JsonSerializer<SecureHash>() { object SecureHashSerializer : JsonSerializer<SecureHash>() {
override fun serialize(obj: SecureHash, generator: JsonGenerator, provider: SerializerProvider) { override fun serialize(obj: SecureHash, generator: JsonGenerator, provider: SerializerProvider) {
generator.writeString(obj.toString()) generator.writeString(obj.toString())
} }
@ -110,9 +102,9 @@ object JsonSupport {
/** /**
* Implemented as a class so that we can instantiate for T * Implemented as a class so that we can instantiate for T
*/ */
class SecureHashDeserializer<T : SecureHash>: JsonDeserializer<T>() { class SecureHashDeserializer<T : SecureHash> : JsonDeserializer<T>() {
override fun deserialize(parser: JsonParser, context: DeserializationContext): T { override fun deserialize(parser: JsonParser, context: DeserializationContext): T {
if(parser.currentToken == JsonToken.FIELD_NAME) { if (parser.currentToken == JsonToken.FIELD_NAME) {
parser.nextToken() parser.nextToken()
} }
try { try {
@ -124,7 +116,7 @@ object JsonSupport {
} }
} }
object CalendarDeserializer: JsonDeserializer<BusinessCalendar>() { object CalendarDeserializer : JsonDeserializer<BusinessCalendar>() {
override fun deserialize(parser: JsonParser, context: DeserializationContext): BusinessCalendar { override fun deserialize(parser: JsonParser, context: DeserializationContext): BusinessCalendar {
return try { return try {
val array = StringArrayDeserializer.instance.deserialize(parser, context) val array = StringArrayDeserializer.instance.deserialize(parser, context)

View File

@ -1,11 +1,3 @@
/*
* Copyright 2015 Distributed Ledger Group LLC. Distributed as Licensed Company IP to DLG Group Members
* pursuant to the August 7, 2015 Advisory Services Agreement and subject to the Company IP License terms
* set forth therein.
*
* All other rights reserved.
*/
package core.utilities package core.utilities
import org.slf4j.LoggerFactory import org.slf4j.LoggerFactory
@ -23,6 +15,7 @@ import kotlin.reflect.KClass
// Kotlin's string interpolation efficiently: the message is never calculated/concatenated together unless // Kotlin's string interpolation efficiently: the message is never calculated/concatenated together unless
// logging at that level is enabled. // logging at that level is enabled.
inline fun <reified T : Any> loggerFor(): org.slf4j.Logger = LoggerFactory.getLogger(T::class.java) inline fun <reified T : Any> loggerFor(): org.slf4j.Logger = LoggerFactory.getLogger(T::class.java)
inline fun org.slf4j.Logger.trace(msg: () -> String) { inline fun org.slf4j.Logger.trace(msg: () -> String) {
if (isTraceEnabled) trace(msg()) if (isTraceEnabled) trace(msg())
} }

View File

@ -1,14 +1,5 @@
/*
* Copyright 2015 Distributed Ledger Group LLC. Distributed as Licensed Company IP to DLG Group Members
* pursuant to the August 7, 2015 Advisory Services Agreement and subject to the Company IP License terms
* set forth therein.
*
* All other rights reserved.
*/
package core.utilities package core.utilities
import core.utilities.loggerFor
import org.slf4j.Logger import org.slf4j.Logger
import java.util.* import java.util.*
import javax.annotation.concurrent.ThreadSafe import javax.annotation.concurrent.ThreadSafe
@ -24,6 +15,7 @@ class RecordingMap<K, V>(private val wrappedMap: MutableMap<K, V>,
private val logger: Logger = loggerFor<RecordingMap<K, V>>()) : MutableMap<K, V> by wrappedMap { private val logger: Logger = loggerFor<RecordingMap<K, V>>()) : MutableMap<K, V> by wrappedMap {
// If/when Kotlin supports data classes inside sealed classes, that would be preferable to this. // If/when Kotlin supports data classes inside sealed classes, that would be preferable to this.
interface Record interface Record
data class Get<K>(val key: K) : Record data class Get<K>(val key: K) : Record
data class Put<K, V>(val key: K, val value: V) : Record data class Put<K, V>(val key: K, val value: V) : Record

View File

@ -1,11 +1,3 @@
/*
* Copyright 2015 Distributed Ledger Group LLC. Distributed as Licensed Company IP to DLG Group Members
* pursuant to the August 7, 2015 Advisory Services Agreement and subject to the Company IP License terms
* set forth therein.
*
* All other rights reserved.
*/
package core.utilities package core.utilities
/** /**

View File

@ -11,9 +11,9 @@ class DemoClock(private var delegateClock: Clock = Clock.systemUTC()) : Clock()
@Synchronized fun updateDate(date: LocalDate): Boolean { @Synchronized fun updateDate(date: LocalDate): Boolean {
val currentDate = LocalDate.now(this) val currentDate = LocalDate.now(this)
if(currentDate.isBefore(date)) { if (currentDate.isBefore(date)) {
// It's ok to increment // It's ok to increment
delegateClock = Clock.offset(delegateClock, Duration.between(currentDate.atStartOfDay(),date.atStartOfDay())) delegateClock = Clock.offset(delegateClock, Duration.between(currentDate.atStartOfDay(), date.atStartOfDay()))
return true return true
} }
return false return false

View File

@ -1,11 +1,3 @@
/*
* Copyright 2015 Distributed Ledger Group LLC. Distributed as Licensed Company IP to DLG Group Members
* pursuant to the August 7, 2015 Advisory Services Agreement and subject to the Company IP License terms
* set forth therein.
*
* All other rights reserved.
*/
package demos package demos
import com.google.common.net.HostAndPort import com.google.common.net.HostAndPort
@ -16,14 +8,14 @@ import core.node.Node
import core.node.NodeConfiguration import core.node.NodeConfiguration
import core.node.NodeConfigurationFromConfig import core.node.NodeConfigurationFromConfig
import core.node.services.ArtemisMessagingService import core.node.services.ArtemisMessagingService
import core.node.services.NodeInfo
import core.node.services.MockNetworkMapCache import core.node.services.MockNetworkMapCache
import core.node.services.NodeInfo
import core.serialization.deserialize import core.serialization.deserialize
import core.utilities.BriefLogFormatter import core.utilities.BriefLogFormatter
import joptsimple.OptionParser
import demos.protocols.AutoOfferProtocol import demos.protocols.AutoOfferProtocol
import demos.protocols.ExitServerProtocol import demos.protocols.ExitServerProtocol
import demos.protocols.UpdateBusinessDayProtocol import demos.protocols.UpdateBusinessDayProtocol
import joptsimple.OptionParser
import java.nio.file.Files import java.nio.file.Files
import java.nio.file.Path import java.nio.file.Path
import java.nio.file.Paths import java.nio.file.Paths
@ -75,7 +67,7 @@ fun main(args: Array<String>) {
val myNetAddr = HostAndPort.fromString(options.valueOf(networkAddressArg)).withDefaultPort(Node.DEFAULT_PORT) val myNetAddr = HostAndPort.fromString(options.valueOf(networkAddressArg)).withDefaultPort(Node.DEFAULT_PORT)
// The timestamping node runs in the same process as the one that passes null to Node constructor. // The timestamping node runs in the same process as the one that passes null to Node constructor.
val timestamperId = if(options.valueOf(timestamperNetAddr).equals(options.valueOf(networkAddressArg))) { val timestamperId = if (options.valueOf(timestamperNetAddr).equals(options.valueOf(networkAddressArg))) {
null null
} else { } else {
try { try {
@ -86,7 +78,7 @@ fun main(args: Array<String>) {
} }
// The timestamping node runs in the same process as the one that passes null to Node constructor. // The timestamping node runs in the same process as the one that passes null to Node constructor.
val rateOracleId = if(options.valueOf(rateOracleNetAddr).equals(options.valueOf(networkAddressArg))) { val rateOracleId = if (options.valueOf(rateOracleNetAddr).equals(options.valueOf(networkAddressArg))) {
null null
} else { } else {
try { try {
@ -106,10 +98,10 @@ fun main(args: Array<String>) {
val hostAndPortStrings = options.valuesOf(fakeTradeWithAddr) val hostAndPortStrings = options.valuesOf(fakeTradeWithAddr)
val identityFiles = options.valuesOf(fakeTradeWithIdentityFile) val identityFiles = options.valuesOf(fakeTradeWithIdentityFile)
if(hostAndPortStrings.size != identityFiles.size) { if (hostAndPortStrings.size != identityFiles.size) {
throw IllegalArgumentException("Different number of peer addresses (${hostAndPortStrings.size}) and identities (${identityFiles.size})") throw IllegalArgumentException("Different number of peer addresses (${hostAndPortStrings.size}) and identities (${identityFiles.size})")
} }
for ((hostAndPortString,identityFile) in hostAndPortStrings.zip(identityFiles)) { for ((hostAndPortString, identityFile) in hostAndPortStrings.zip(identityFiles)) {
try { try {
val peerId = nodeInfo(hostAndPortString, identityFile) val peerId = nodeInfo(hostAndPortString, identityFile)
(node.services.networkMapCache as MockNetworkMapCache).partyNodes.add(peerId) (node.services.networkMapCache as MockNetworkMapCache).partyNodes.add(peerId)
@ -122,8 +114,10 @@ fun main(args: Array<String>) {
UpdateBusinessDayProtocol.Handler.register(node) UpdateBusinessDayProtocol.Handler.register(node)
ExitServerProtocol.Handler.register(node) ExitServerProtocol.Handler.register(node)
while(true) { try {
Thread.sleep(1000L) while (true) Thread.sleep(Long.MAX_VALUE)
} catch(e: InterruptedException) {
node.stop()
} }
exitProcess(0) exitProcess(0)
} }

View File

@ -1,11 +1,3 @@
/*
* Copyright 2015 Distributed Ledger Group LLC. Distributed as Licensed Company IP to DLG Group Members
* pursuant to the August 7, 2015 Advisory Services Agreement and subject to the Company IP License terms
* set forth therein.
*
* All other rights reserved.
*/
package demos package demos
import contracts.Cash import contracts.Cash

View File

@ -1,11 +1,3 @@
/*
* Copyright 2015 Distributed Ledger Group LLC. Distributed as Licensed Company IP to DLG Group Members
* pursuant to the August 7, 2015 Advisory Services Agreement and subject to the Company IP License terms
* set forth therein.
*
* All other rights reserved.
*/
package demos package demos
import co.paralleluniverse.fibers.Suspendable import co.paralleluniverse.fibers.Suspendable
@ -20,8 +12,8 @@ import core.node.Node
import core.node.NodeConfiguration import core.node.NodeConfiguration
import core.node.NodeConfigurationFromConfig import core.node.NodeConfigurationFromConfig
import core.node.services.ArtemisMessagingService import core.node.services.ArtemisMessagingService
import core.node.services.NodeInfo
import core.node.services.NodeAttachmentService import core.node.services.NodeAttachmentService
import core.node.services.NodeInfo
import core.node.services.NodeWalletService import core.node.services.NodeWalletService
import core.protocols.ProtocolLogic import core.protocols.ProtocolLogic
import core.serialization.deserialize import core.serialization.deserialize
@ -242,7 +234,7 @@ class TraderDemoProtocolSeller(val myAddress: HostAndPort,
val party = Party("Bank of London", keyPair.public) val party = Party("Bank of London", keyPair.public)
val issuance = run { val issuance = run {
val tx = CommercialPaper().generateIssue(party.ref(1,2,3), 1100.DOLLARS, Instant.now() + 10.days) val tx = CommercialPaper().generateIssue(party.ref(1, 2, 3), 1100.DOLLARS, Instant.now() + 10.days)
// TODO: Consider moving these two steps below into generateIssue. // TODO: Consider moving these two steps below into generateIssue.

View File

@ -107,8 +107,8 @@ object AutoOfferProtocol {
} }
fun notUs(vararg parties: Party): List<Party> { fun notUs(vararg parties: Party): List<Party> {
val notUsParties : MutableList<Party> = arrayListOf() val notUsParties: MutableList<Party> = arrayListOf()
for(party in parties) { for (party in parties) {
if (serviceHub.storageService.myLegalIdentity != party) { if (serviceHub.storageService.myLegalIdentity != party) {
notUsParties.add(party) notUsParties.add(party)
} }

View File

@ -3,8 +3,8 @@ package demos.protocols
import co.paralleluniverse.fibers.Suspendable import co.paralleluniverse.fibers.Suspendable
import co.paralleluniverse.strands.Strand import co.paralleluniverse.strands.Strand
import core.node.Node import core.node.Node
import core.node.services.NodeInfo
import core.node.services.MockNetworkMapCache import core.node.services.MockNetworkMapCache
import core.node.services.NodeInfo
import core.protocols.ProtocolLogic import core.protocols.ProtocolLogic
import core.serialization.deserialize import core.serialization.deserialize
import java.util.concurrent.TimeUnit import java.util.concurrent.TimeUnit
@ -24,7 +24,7 @@ object ExitServerProtocol {
fun register(node: Node) { fun register(node: Node) {
node.net.addMessageHandler("${TOPIC}.0") { msg, registration -> node.net.addMessageHandler("${TOPIC}.0") { msg, registration ->
// Just to validate we got the message // Just to validate we got the message
if(enabled) { if (enabled) {
val message = msg.data.deserialize<ExitMessage>() val message = msg.data.deserialize<ExitMessage>()
System.exit(message.exitCode) System.exit(message.exitCode)
} }
@ -37,11 +37,11 @@ object ExitServerProtocol {
* This takes a Java Integer rather than Kotlin Int as that is what we end up with in the calling map and currently * This takes a Java Integer rather than Kotlin Int as that is what we end up with in the calling map and currently
* we do not support coercing numeric types in the reflective search for matching constructors * we do not support coercing numeric types in the reflective search for matching constructors
*/ */
class Broadcast(val exitCode: Integer) : ProtocolLogic<Boolean>() { class Broadcast(@Suppress("PLATFORM_CLASS_MAPPED_TO_KOTLIN") val exitCode: Integer) : ProtocolLogic<Boolean>() {
@Suspendable @Suspendable
override fun call(): Boolean { override fun call(): Boolean {
if(enabled) { if (enabled) {
val rc = exitCode.toInt() val rc = exitCode.toInt()
val message = ExitMessage(rc) val message = ExitMessage(rc)
@ -57,7 +57,7 @@ object ExitServerProtocol {
@Suspendable @Suspendable
private fun doNextRecipient(recipient: NodeInfo, message: ExitMessage) { private fun doNextRecipient(recipient: NodeInfo, message: ExitMessage) {
if(recipient.address is MockNetworkMapCache.MockAddress) { if (recipient.address is MockNetworkMapCache.MockAddress) {
// Ignore // Ignore
} else { } else {
// TODO: messaging ourselves seems to trigger a bug for the time being and we continuously receive messages // TODO: messaging ourselves seems to trigger a bug for the time being and we continuously receive messages

View File

@ -6,8 +6,9 @@ import contracts.DealState
import contracts.InterestRateSwap import contracts.InterestRateSwap
import core.StateAndRef import core.StateAndRef
import core.node.Node import core.node.Node
import core.node.services.NodeInfo
import core.node.services.MockNetworkMapCache import core.node.services.MockNetworkMapCache
import core.node.services.NodeInfo
import core.node.services.linearHeadsOfType
import core.protocols.ProtocolLogic import core.protocols.ProtocolLogic
import core.random63BitValue import core.random63BitValue
import core.serialization.deserialize import core.serialization.deserialize
@ -41,14 +42,14 @@ object UpdateBusinessDayProtocol {
override fun call(): Boolean { override fun call(): Boolean {
// Get deals // Get deals
progressTracker.currentStep = FETCHING progressTracker.currentStep = FETCHING
val dealStateRefs = serviceHub.walletService.linearHeadsInstanceOf(DealState::class.java) val dealStateRefs = serviceHub.walletService.linearHeadsOfType<DealState>()
val otherPartyToDeals = dealStateRefs.values.groupBy { otherParty(it.state) } val otherPartyToDeals = dealStateRefs.values.groupBy { otherParty(it.state) }
// TODO we need to process these in parallel to stop there being an ordering problem across more than two nodes // TODO we need to process these in parallel to stop there being an ordering problem across more than two nodes
val sortedParties = otherPartyToDeals.keys.sortedBy { it.identity.name } val sortedParties = otherPartyToDeals.keys.sortedBy { it.identity.name }
for (party in sortedParties) { for (party in sortedParties) {
val sortedDeals = otherPartyToDeals[party]!!.sortedBy { it.state.ref } val sortedDeals = otherPartyToDeals[party]!!.sortedBy { it.state.ref }
for(deal in sortedDeals) { for (deal in sortedDeals) {
progressTracker.currentStep = ITERATING_DEALS progressTracker.currentStep = ITERATING_DEALS
processDeal(party, deal, date, sessionID) processDeal(party, deal, date, sessionID)
} }
@ -65,8 +66,9 @@ object UpdateBusinessDayProtocol {
// TODO we should make this more object oriented when we can ask a state for it's contract // TODO we should make this more object oriented when we can ask a state for it's contract
@Suspendable @Suspendable
fun processDeal(party: NodeInfo, deal: StateAndRef<DealState>, date: LocalDate, sessionID: Long) { fun processDeal(party: NodeInfo, deal: StateAndRef<DealState>, date: LocalDate, sessionID: Long) {
when(deal.state) { val s = deal.state
is InterestRateSwap.State -> processInterestRateSwap(party, StateAndRef(deal.state as InterestRateSwap.State, deal.ref), date, sessionID) when (s) {
is InterestRateSwap.State -> processInterestRateSwap(party, StateAndRef(s, deal.ref), date, sessionID)
} }
} }
@ -160,7 +162,7 @@ object UpdateBusinessDayProtocol {
@Suspendable @Suspendable
private fun doNextRecipient(recipient: NodeInfo, message: UpdateBusinessDayMessage) { private fun doNextRecipient(recipient: NodeInfo, message: UpdateBusinessDayMessage) {
if(recipient.address is MockNetworkMapCache.MockAddress) { if (recipient.address is MockNetworkMapCache.MockAddress) {
// Ignore // Ignore
} else { } else {
// TODO: messaging ourselves seems to trigger a bug for the time being and we continuously receive messages // TODO: messaging ourselves seems to trigger a bug for the time being and we continuously receive messages

View File

@ -1,11 +1,3 @@
/*
* Copyright 2015 Distributed Ledger Group LLC. Distributed as Licensed Company IP to DLG Group Members
* pursuant to the August 7, 2015 Advisory Services Agreement and subject to the Company IP License terms
* set forth therein.
*
* All other rights reserved.
*/
package protocols package protocols
import core.Attachment import core.Attachment

View File

@ -1,11 +1,3 @@
/*
* Copyright 2015 Distributed Ledger Group LLC. Distributed as Licensed Company IP to DLG Group Members
* pursuant to the August 7, 2015 Advisory Services Agreement and subject to the Company IP License terms
* set forth therein.
*
* All other rights reserved.
*/
package protocols package protocols
import co.paralleluniverse.fibers.Suspendable import co.paralleluniverse.fibers.Suspendable

View File

@ -1,11 +1,3 @@
/*
* Copyright 2015 Distributed Ledger Group LLC. Distributed as Licensed Company IP to DLG Group Members
* pursuant to the August 7, 2015 Advisory Services Agreement and subject to the Company IP License terms
* set forth therein.
*
* All other rights reserved.
*/
package protocols package protocols
import core.SignedTransaction import core.SignedTransaction

View File

@ -1,11 +1,3 @@
/*
* Copyright 2015 Distributed Ledger Group LLC. Distributed as Licensed Company IP to DLG Group Members
* pursuant to the August 7, 2015 Advisory Services Agreement and subject to the Company IP License terms
* set forth therein.
*
* All other rights reserved.
*/
package protocols package protocols
import co.paralleluniverse.fibers.Suspendable import co.paralleluniverse.fibers.Suspendable

View File

@ -1,11 +1,3 @@
/*
* Copyright 2015 Distributed Ledger Group LLC. Distributed as Licensed Company IP to DLG Group Members
* pursuant to the August 7, 2015 Advisory Services Agreement and subject to the Company IP License terms
* set forth therein.
*
* All other rights reserved.
*/
package protocols package protocols
import co.paralleluniverse.fibers.Suspendable import co.paralleluniverse.fibers.Suspendable

View File

@ -1,11 +1,3 @@
/*
* Copyright 2015 Distributed Ledger Group LLC. Distributed as Licensed Company IP to DLG Group Members
* pursuant to the August 7, 2015 Advisory Services Agreement and subject to the Company IP License terms
* set forth therein.
*
* All other rights reserved.
*/
package protocols package protocols
import co.paralleluniverse.fibers.Suspendable import co.paralleluniverse.fibers.Suspendable
@ -51,7 +43,6 @@ class TimestampingProtocol(private val node: NodeInfo,
} }
@Suspendable @Suspendable
override fun call(): DigitalSignature.LegallyIdentifiable { override fun call(): DigitalSignature.LegallyIdentifiable {
progressTracker.currentStep = REQUESTING progressTracker.currentStep = REQUESTING

View File

@ -1,11 +1,3 @@
/*
* Copyright 2015 Distributed Ledger Group LLC. Distributed as Licensed Company IP to DLG Group Members
* pursuant to the August 7, 2015 Advisory Services Agreement and subject to the Company IP License terms
* set forth therein.
*
* All other rights reserved.
*/
package protocols package protocols
import co.paralleluniverse.fibers.Suspendable import co.paralleluniverse.fibers.Suspendable
@ -239,7 +231,7 @@ object TwoPartyDealProtocol {
private fun receiveAndValidateHandshake(): Handshake<U> { private fun receiveAndValidateHandshake(): Handshake<U> {
progressTracker.currentStep = RECEIVING progressTracker.currentStep = RECEIVING
// Wait for a trade request to come in on our pre-provided session ID. // Wait for a trade request to come in on our pre-provided session ID.
val handshake = receive(DEAL_TOPIC, sessionID, Handshake::class.java) val handshake = receive<Handshake<U>>(DEAL_TOPIC, sessionID)
progressTracker.currentStep = VERIFYING progressTracker.currentStep = VERIFYING
handshake.validate { handshake.validate {
@ -267,7 +259,7 @@ object TwoPartyDealProtocol {
return ptx.toSignedTransaction(checkSufficientSignatures = false) return ptx.toSignedTransaction(checkSufficientSignatures = false)
} }
@Suspendable protected abstract fun validateHandshake(handshake: Handshake<*>): Handshake<U> @Suspendable protected abstract fun validateHandshake(handshake: Handshake<U>): Handshake<U>
@Suspendable protected abstract fun assembleSharedTX(handshake: Handshake<U>): Pair<TransactionBuilder, List<PublicKey>> @Suspendable protected abstract fun assembleSharedTX(handshake: Handshake<U>): Pair<TransactionBuilder, List<PublicKey>>
} }
@ -291,10 +283,10 @@ object TwoPartyDealProtocol {
override val progressTracker: ProgressTracker = Secondary.tracker()) : Secondary<T>(otherSide, timestampingAuthority, sessionID) { override val progressTracker: ProgressTracker = Secondary.tracker()) : Secondary<T>(otherSide, timestampingAuthority, sessionID) {
@Suspendable @Suspendable
override fun validateHandshake(handshake: Handshake<*>): Handshake<T> { override fun validateHandshake(handshake: Handshake<T>): Handshake<T> {
with(handshake as Handshake<T>) { with(handshake) {
// What is the seller trying to sell us? // What is the seller trying to sell us?
val deal = handshake.payload val deal: T = handshake.payload
val otherKey = handshake.publicKey val otherKey = handshake.publicKey
logger.trace { "Got deal request for: ${handshake.payload}" } logger.trace { "Got deal request for: ${handshake.payload}" }
@ -308,7 +300,10 @@ object TwoPartyDealProtocol {
val myOldParty = deal.parties.single { it.name == myName } val myOldParty = deal.parties.single { it.name == myName }
val theirOldParty = deal.parties.single { it.name != myName } val theirOldParty = deal.parties.single { it.name != myName }
val newDeal = deal.withPublicKey(myOldParty, serviceHub.keyManagementService.freshKey().public).withPublicKey(theirOldParty, otherKey) as T @Suppress("UNCHECKED_CAST")
val newDeal = deal.
withPublicKey(myOldParty, serviceHub.keyManagementService.freshKey().public).
withPublicKey(theirOldParty, otherKey) as T
return handshake.copy(payload = newDeal) return handshake.copy(payload = newDeal)
} }
@ -341,8 +336,8 @@ object TwoPartyDealProtocol {
override val progressTracker: ProgressTracker = Secondary.tracker()) : Secondary<StateRef>(otherSide, timestampingAuthority, sessionID) { override val progressTracker: ProgressTracker = Secondary.tracker()) : Secondary<StateRef>(otherSide, timestampingAuthority, sessionID) {
@Suspendable @Suspendable
override fun validateHandshake(handshake: Handshake<*>): Handshake<StateRef> { override fun validateHandshake(handshake: Handshake<StateRef>): Handshake<StateRef> {
with(handshake as Handshake<StateRef>) { with(handshake) {
logger.trace { "Got fixing request for: ${dealToFix.state}" } logger.trace { "Got fixing request for: ${dealToFix.state}" }
// Check the start message for acceptability. // Check the start message for acceptability.
@ -363,11 +358,12 @@ object TwoPartyDealProtocol {
// TODO Do we need/want to substitute in new public keys for the Parties? // TODO Do we need/want to substitute in new public keys for the Parties?
val myName = serviceHub.storageService.myLegalIdentity.name val myName = serviceHub.storageService.myLegalIdentity.name
val deal = dealToFix.state val deal: T = dealToFix.state
val myOldParty = deal.parties.single { it.name == myName } val myOldParty = deal.parties.single { it.name == myName }
val theirOldParty = deal.parties.single { it.name != myName } val theirOldParty = deal.parties.single { it.name != myName }
val myNewKey = serviceHub.keyManagementService.freshKey().public val myNewKey = serviceHub.keyManagementService.freshKey().public
@Suppress("UNCHECKED_CAST")
val newDeal = deal.withPublicKey(myOldParty, myNewKey).withPublicKey(theirOldParty, handshake.publicKey) as T val newDeal = deal.withPublicKey(myOldParty, myNewKey).withPublicKey(theirOldParty, handshake.publicKey) as T
val oldRef = dealToFix.ref val oldRef = dealToFix.ref

View File

@ -1,11 +1,3 @@
/*
* Copyright 2015 Distributed Ledger Group LLC. Distributed as Licensed Company IP to DLG Group Members
* pursuant to the August 7, 2015 Advisory Services Agreement and subject to the Company IP License terms
* set forth therein.
*
* All other rights reserved.
*/
package protocols package protocols
import co.paralleluniverse.fibers.Suspendable import co.paralleluniverse.fibers.Suspendable

View File

@ -1,13 +1,5 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<!--
~ Copyright 2015 Distributed Ledger Group LLC. Distributed as Licensed Company IP to DLG Group Members
~ pursuant to the August 7, 2015 Advisory Services Agreement and subject to the Company IP License terms
~ set forth therein.
~
~ All other rights reserved.
-->
<restrict> <restrict>
<http> <http>
<method>post</method> <method>post</method>

View File

@ -1,11 +1,3 @@
/*
* Copyright 2015 Distributed Ledger Group LLC. Distributed as Licensed Company IP to DLG Group Members
* pursuant to the August 7, 2015 Advisory Services Agreement and subject to the Company IP License terms
* set forth therein.
*
* All other rights reserved.
*/
package core.crypto; package core.crypto;
import org.junit.*; import org.junit.*;
@ -13,11 +5,11 @@ import org.junit.*;
import java.math.*; import java.math.*;
import java.util.*; import java.util.*;
import static org.junit.Assert.assertEquals; import static org.junit.Assert.*;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
/** From the bitcoinj library */ /**
* From the bitcoinj library
*/
public class Base58Test { public class Base58Test {
@Test @Test
public void testEncode() throws Exception { public void testEncode() throws Exception {

View File

@ -37,7 +37,7 @@ class CashTests {
this `fails requirement` "the amounts balance" this `fails requirement` "the amounts balance"
tweak { tweak {
output { outState.copy(amount = 2000.DOLLARS )} output { outState.copy(amount = 2000.DOLLARS) }
this `fails requirement` "the amounts balance" this `fails requirement` "the amounts balance"
} }
tweak { tweak {
@ -100,7 +100,7 @@ class CashTests {
} }
val ptx = TransactionBuilder() val ptx = TransactionBuilder()
Cash().generateIssue(ptx, 100.DOLLARS, MINI_CORP.ref(12,34), owner = DUMMY_PUBKEY_1) Cash().generateIssue(ptx, 100.DOLLARS, MINI_CORP.ref(12, 34), owner = DUMMY_PUBKEY_1)
assertTrue(ptx.inputStates().isEmpty()) assertTrue(ptx.inputStates().isEmpty())
val s = ptx.outputStates()[0] as Cash.State val s = ptx.outputStates()[0] as Cash.State
assertEquals(100.DOLLARS, s.amount) assertEquals(100.DOLLARS, s.amount)

View File

@ -1,11 +1,3 @@
/*
* Copyright 2015 Distributed Ledger Group LLC. Distributed as Licensed Company IP to DLG Group Members
* pursuant to the August 7, 2015 Advisory Services Agreement and subject to the Company IP License terms
* set forth therein.
*
* All other rights reserved.
*/
package contracts package contracts
import core.* import core.*
@ -43,12 +35,13 @@ class JavaCommercialPaperTest() : ICommercialPaperTestTemplate {
} }
class KotlinCommercialPaperTest() : ICommercialPaperTestTemplate { class KotlinCommercialPaperTest() : ICommercialPaperTestTemplate {
override fun getPaper() : ICommercialPaperState = CommercialPaper.State( override fun getPaper(): ICommercialPaperState = CommercialPaper.State(
issuance = MEGA_CORP.ref(123), issuance = MEGA_CORP.ref(123),
owner = MEGA_CORP_PUBKEY, owner = MEGA_CORP_PUBKEY,
faceValue = 1000.DOLLARS, faceValue = 1000.DOLLARS,
maturityDate = TEST_TX_TIME + 7.days maturityDate = TEST_TX_TIME + 7.days
) )
override fun getIssueCommand(): CommandData = CommercialPaper.Commands.Issue() override fun getIssueCommand(): CommandData = CommercialPaper.Commands.Issue()
override fun getRedeemCommand(): CommandData = CommercialPaper.Commands.Redeem() override fun getRedeemCommand(): CommandData = CommercialPaper.Commands.Redeem()
override fun getMoveCommand(): CommandData = CommercialPaper.Commands.Move() override fun getMoveCommand(): CommandData = CommercialPaper.Commands.Move()

View File

@ -1,11 +1,3 @@
/*
* Copyright 2015 Distributed Ledger Group LLC. Distributed as Licensed Company IP to DLG Group Members
* pursuant to the August 7, 2015 Advisory Services Agreement and subject to the Company IP License terms
* set forth therein.
*
* All other rights reserved.
*/
package contracts package contracts
import core.* import core.*

View File

@ -1,11 +1,3 @@
/*
* Copyright 2015 Distributed Ledger Group LLC. Distributed as Licensed Company IP to DLG Group Members
* pursuant to the August 7, 2015 Advisory Services Agreement and subject to the Company IP License terms
* set forth therein.
*
* All other rights reserved.
*/
package contracts package contracts
import core.* import core.*
@ -16,7 +8,7 @@ import java.time.LocalDate
import java.util.* import java.util.*
fun createDummyIRS(irsSelect: Int): InterestRateSwap.State { fun createDummyIRS(irsSelect: Int): InterestRateSwap.State {
return when(irsSelect) { return when (irsSelect) {
1 -> { 1 -> {
val fixedLeg = InterestRateSwap.FixedLeg( val fixedLeg = InterestRateSwap.FixedLeg(
@ -326,19 +318,9 @@ class IRSTests {
assert(100 * r1 == 5) assert(100 * r1 == 5)
} }
@Test
fun `more rate tests`() {
val r1 = FixedRate(PercentageRatioUnit("10"))
val r2 = FixedRate(PercentageRatioUnit("10"))
// TODO: r1+r2 ? Do we want to allow these.
// TODO: r1*r2 ?
}
@Test @Test
fun `expression calculation testing`() { fun `expression calculation testing`() {
val dummyIRS = singleIRS() val dummyIRS = singleIRS()
val v = FixedRate(PercentageRatioUnit("4.5"))
val stuffToPrint: ArrayList<String> = arrayListOf( val stuffToPrint: ArrayList<String> = arrayListOf(
"fixedLeg.notional.pennies", "fixedLeg.notional.pennies",
"fixedLeg.fixedRate.ratioUnit", "fixedLeg.fixedRate.ratioUnit",

View File

@ -1,11 +1,3 @@
/*
* Copyright 2015 Distributed Ledger Group LLC. Distributed as Licensed Company IP to DLG Group Members
* pursuant to the August 7, 2015 Advisory Services Agreement and subject to the Company IP License terms
* set forth therein.
*
* All other rights reserved.
*/
package core package core
import com.codahale.metrics.MetricRegistry import com.codahale.metrics.MetricRegistry

View File

@ -1,11 +1,3 @@
/*
* Copyright 2015 Distributed Ledger Group LLC. Distributed as Licensed Company IP to DLG Group Members
* pursuant to the August 7, 2015 Advisory Services Agreement and subject to the Company IP License terms
* set forth therein.
*
* All other rights reserved.
*/
package core package core
import contracts.Cash import contracts.Cash

View File

@ -1,19 +1,11 @@
/*
* Copyright 2015 Distributed Ledger Group LLC. Distributed as Licensed Company IP to DLG Group Members
* pursuant to the August 7, 2015 Advisory Services Agreement and subject to the Company IP License terms
* set forth therein.
*
* All other rights reserved.
*/
package core.messaging package core.messaging
import core.Attachment import core.Attachment
import core.crypto.SecureHash import core.crypto.SecureHash
import core.crypto.sha256 import core.crypto.sha256
import core.node.NodeConfiguration import core.node.NodeConfiguration
import core.node.services.NodeInfo
import core.node.services.NodeAttachmentService import core.node.services.NodeAttachmentService
import core.node.services.NodeInfo
import core.serialization.OpaqueBytes import core.serialization.OpaqueBytes
import core.testing.MockNetwork import core.testing.MockNetwork
import core.testutils.rootCauseExceptions import core.testutils.rootCauseExceptions

View File

@ -1,11 +1,3 @@
/*
* Copyright 2015 Distributed Ledger Group LLC. Distributed as Licensed Company IP to DLG Group Members
* pursuant to the August 7, 2015 Advisory Services Agreement and subject to the Company IP License terms
* set forth therein.
*
* All other rights reserved.
*/
@file:Suppress("UNUSED_VARIABLE") @file:Suppress("UNUSED_VARIABLE")
package core.messaging package core.messaging
@ -54,7 +46,8 @@ open class TestWithInMemoryNetwork {
} }
fun runNetwork() { fun runNetwork() {
while (pumpAll(false).any { it }) {} while (pumpAll(false).any { it }) {
}
} }
} }

View File

@ -1,11 +1,3 @@
/*
* Copyright 2015 Distributed Ledger Group LLC. Distributed as Licensed Company IP to DLG Group Members
* pursuant to the August 7, 2015 Advisory Services Agreement and subject to the Company IP License terms
* set forth therein.
*
* All other rights reserved.
*/
package core.messaging package core.messaging
import contracts.Cash import contracts.Cash
@ -112,11 +104,6 @@ class TwoPartyTradeProtocolTests : TestWithInMemoryNetwork() {
insertFakeTransactions(alicesFakePaper, aliceNode.services, aliceNode.storage.myLegalIdentityKey) insertFakeTransactions(alicesFakePaper, aliceNode.services, aliceNode.storage.myLegalIdentityKey)
// Horrible Gradle/Kryo/Quasar FUBAR workaround: just skip these tests when run under Gradle for now.
// TODO: Fix this once Quasar issue 153 is resolved.
if (!bobNode.smm.checkpointing)
return
val buyerSessionID = random63BitValue() val buyerSessionID = random63BitValue()
val aliceFuture = TwoPartyTradeProtocol.runSeller( val aliceFuture = TwoPartyTradeProtocol.runSeller(
@ -140,6 +127,7 @@ class TwoPartyTradeProtocolTests : TestWithInMemoryNetwork() {
// Everything is on this thread so we can now step through the protocol one step at a time. // Everything is on this thread so we can now step through the protocol one step at a time.
// Seller Alice already sent a message to Buyer Bob. Pump once: // Seller Alice already sent a message to Buyer Bob. Pump once:
fun pumpAlice() = (aliceNode.net as InMemoryMessagingNetwork.InMemoryMessaging).pump(false) fun pumpAlice() = (aliceNode.net as InMemoryMessagingNetwork.InMemoryMessaging).pump(false)
fun pumpBob() = (bobNode.net as InMemoryMessagingNetwork.InMemoryMessaging).pump(false) fun pumpBob() = (bobNode.net as InMemoryMessagingNetwork.InMemoryMessaging).pump(false)
pumpBob() pumpBob()

View File

@ -1,11 +1,3 @@
/*
* Copyright 2015 Distributed Ledger Group LLC. Distributed as Licensed Company IP to DLG Group Members
* pursuant to the August 7, 2015 Advisory Services Agreement and subject to the Company IP License terms
* set forth therein.
*
* All other rights reserved.
*/
package core.node package core.node
import com.codahale.metrics.MetricRegistry import com.codahale.metrics.MetricRegistry

View File

@ -1,11 +1,3 @@
/*
* Copyright 2015 Distributed Ledger Group LLC. Distributed as Licensed Company IP to DLG Group Members
* pursuant to the August 7, 2015 Advisory Services Agreement and subject to the Company IP License terms
* set forth therein.
*
* All other rights reserved.
*/
package core.node package core.node
import contracts.Cash import contracts.Cash

View File

@ -1,11 +1,3 @@
/*
* Copyright 2015 Distributed Ledger Group LLC. Distributed as Licensed Company IP to DLG Group Members
* pursuant to the August 7, 2015 Advisory Services Agreement and subject to the Company IP License terms
* set forth therein.
*
* All other rights reserved.
*/
package core.node package core.node
import co.paralleluniverse.fibers.Suspendable import co.paralleluniverse.fibers.Suspendable

View File

@ -1,11 +1,3 @@
/*
* Copyright 2015 Distributed Ledger Group LLC. Distributed as Licensed Company IP to DLG Group Members
* pursuant to the August 7, 2015 Advisory Services Agreement and subject to the Company IP License terms
* set forth therein.
*
* All other rights reserved.
*/
package core.node.services package core.node.services
import contracts.Cash import contracts.Cash

Some files were not shown because too many files have changed in this diff Show More